-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add relationship interfaces and deprecate bunch of cache/model methods #240
Conversation
This PR also reduces usage of |
331a0dd
to
9ebb788
Compare
@tchak the relationship interfaces are extremely promising! I wonder if it would feel more natural to access
How are changes in the associated cache used to invalidate these arrays? We of course need to ensure that |
@dgeb I don't understand your example. If |
@tchak Sorry, I misplaced the |
Well this will completely work because we invalidate |
I was thinking about how we invalidate each liveQuery but now that I'm reviewing the code I see that we invalidate the relationships via https://github.com/orbitjs/ember-orbit/blob/master/addon/-private/cache.ts#L361-L365 Sorry, I should have just re-checked that logic in the first place! Anyway, let me do a more in depth review of this PR now ... |
The main reason I prefer |
I can see how the distinction is useful for typing, and it's one we already make for query expressions such as For consistency with those query expressions, I wonder if I'm also wondering whether Here is an alternative naming proposal to discuss: class Model {
relatedRecord(relationship: string): RecordRelation;
relatedRecords(relationship: string): RecordsRelation;
}
class Relation {
readonly name: string;
readonly owner: Model;
}
class RecordRelation extends Relation {
get value(): Model | null;
get id(): string | null;
query(options?: object): Promise<Model | null>;
replace(record: RecordIdentity | null, options?: object): Promise<void>;
}
class RecordsRelation extends Relation {
get value(): Model[];
get ids(): string[];
query(options?: object): Promise<Model[]>;
add(record: RecordIdentity, options?: object): Promise<void>;
remove(record: RecordIdentity, options?: object): Promise<void>;
replace(records: RecordIdentity[], options?: object): Promise<void>;
} |
There seems to be a good opportunity to align with #241 here:
And even:
|
I agree on I think |
So maybe: class Model {
hasOneRelation(relationship: string): HasOneRelation;
hasManyRelation(relationship: string): HasManyRelation;
} or class Model {
recordRelation(relationship: string): RecordRelation;
recordsRelation(relationship: string): RecordsRelation;
} |
hmm, I see what you suggesting with aligning store and record interfaces. I think there is a useful distinction between: store.findRecords('planet').peek(); // query the cache and store.peekRecords('planet'); // get raw cache content The second is equivalent to |
class Store {
record<M = Model>(identifier: RecordIdentity): RecordQueryBuilder;
records<M = Model>(identifier: RecordIdentity): RecordsQueryBuilder;
cache: Cache;
}
class Cache {
record<M = Model>(identifier: RecordIdentity): M | undefined;
records<M = Model>(identifier: RecordIdentity): M[] | undefined;
relatedRecord<M = Model>(identifier: RecordIdentity, relationship: string): M | null | undefined;
relatedRecords<M = Model>(identifier: RecordIdentity, relationship: string): M[] | undefined;
has(identifier: RecordIdentity): boolean;
raw(identifier: RecordIdentity): Record | undefined;
}
class QueryBuilder<T> {
filter(): this;
sort(): this;
page(): this;
raw(): this<Record>;
query(): Promise<T>;
peek(): T;
}
class RecordQueryBuilder<M> extends QueryBuilder<M> {
}
class RecordsQueryBuilder<M> extends QueryBuilder<M[]> {
live(): this;
}
class Model {
relatedRecord<M = Model>(relationship: string): RecordRelation;
relatedRecords<M = Model>(relationship: string): RecordsRelation;
}
class Relation<O, T> extends QueryBuilder<T> {
readonly name: string;
readonly owner: O;
}
class RecordRelation<O, M> extends Relation<O, M | null> {
get value(): M | null;
get id(): string | null;
replace(record: RecordIdentity | null, options?: object): Promise<void>;
}
class RecordsRelation<O, M> extends Relation<O, M[]> {
get value(): M[];
get ids(): string[];
live(): this;
add(record: RecordIdentity, options?: object): Promise<void>;
remove(record: RecordIdentity, options?: object): Promise<void>;
replace(records: RecordIdentity[], options?: object): Promise<void>;
} So this is what I have so far:
and
This looks good, but I don't really like the mix of |
I guess we could do : planet.relatedRecords('moons').filter().peek()
planet.relatedRecords('moons').filter().query()
planet.relatedRecords('moons').filter().live().peek()
planet.recordsRelation('moons').value
planet.recordsRelation('moons').add() |
superseded by #278 |
This PR is adding a
Relationship
interface. It is similar to ember-dataReference
interface. The mane goal is to provide a more consistent and smaller API surface.