Skip to content
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

RFC for reference unification #57

Closed
wants to merge 1 commit into from

Conversation

wycats
Copy link
Member

@wycats wycats commented May 23, 2015

@igorT
Copy link
Member

igorT commented May 24, 2015

Several concerns that were raised in the Slack room:

  1. It seems like people would want to manipulate relationships based on just having the reference, and not having the full object. Is this supported behavior? Basically setting a belongsTo to a reference.

  2. It will be easy for references to end up in the dom, see for example:

    {{each post.comments as |comment|}}
         {{linkTo 'comment' comment.id}}
    {{/each}}
    

    If we want to, how do we stop this? How do we enable this use case?

  3. Lets say you want to filer all the comments whose id is not equal to 1. That CP is going to be annoying/hard to write, because you will need to be filtering on relationshipReferences, but the CP will not be able to observe those, it can only observe comments.@each.id or something like that.

@igorT
Copy link
Member

igorT commented May 25, 2015

emberjs/data#2264 seems relevant

@thomassnielsen
Copy link
Contributor

I like this a whole lot, and it would solve many of the use cases where we today have unnecessary fetches against the server and/or usage of private APIs. I also agree that the drawbacks seems worth it as described.

What I'm missing currently is details on how (and if) this will affect current APIs. Especially what Igor describes in point 2, about references not leaking into record arrays (see emberjs/data#2375 for a similar issue). As I see it, the current APIs should maintain only showing loaded records, and references should only show up when using the new reference APIs. Any and all template usage should only show loaded records. I think it would be helpful if this is more explicitly stated in the RFC (if this is indeed the intent).

I also think what Igor describes in point 1 should be implemented if possible without increasing complexity too much. Being able to manipulate relationships based on reference would save a lot of API calls and increase performance in several apps I'm currently working on.

@sandstrom
Copy link
Contributor

Looks great! ⛵ We have a few places where we need to determining if a reference exist without triggering a server-fetch. This would allows us to move off the private APIs we're currently using.


Not 100% related, but it would allow for a JSON-API adapter to sub-class RecordArray and add a loadNext method, utilizing pagination metadata coupled with the metadata on the reference, to retrieve, say, the next 100 comments for a post.

@wycats
Copy link
Member Author

wycats commented May 28, 2015

It seems like people would want to manipulate relationships based on just having the reference, and not having the full object. Is this supported behavior? Basically setting a belongsTo to a reference.

The current proposal does not support mutation, but I would be happy to add it if people need it. Perhaps: reference.update({ ... }). I'm not sure if it makes sense to support updating everything (like id) but maybe it is?

It will be easy for references to end up in the dom, see for example:

I don't understand how your example puts references in the DOM. Can you give me the JS code that produces this?

How do we enable this use case?

Can you flesh out the use-case?

Lets say you want to filer all the comments whose id is not equal to 1. That CP is going to be annoying/hard to write, because you will need to be filtering on relationshipReferences, but the CP will not be able to observe those, it can only observe comments.@each.id or something like that

This proposal doesn't address that case. Do you think it's important to solve it now? If so, I can give it some thought.

@igorT
Copy link
Member

igorT commented May 28, 2015

{{each post.commentReferences as |comment|}}
     {{linkTo 'comment' comment.id}}
{{/each}}

@fivetanley
Copy link
Member

More discussion on getting the ids in a template here as well: worth reviewing emberjs/data#3025

cc @chancancode

@igorT
Copy link
Member

igorT commented May 31, 2015

Another use case is to want to bind to isLoading or isReloading of the relationship

@wecc
Copy link

wecc commented May 31, 2015

Comment from @igorT:

@tomdale and @wycats are to write up a nice example on how to get IDs and how to use isLoaded

@jdurand
Copy link

jdurand commented Jun 25, 2015

I used to do this the non-public (dirty) way with province.data.country_id. I upgraded to ember 1.13.2 and ember-data 1.13.4 and the foreign key ids are not accessible through model.data anymore.

I'd like to quick-fix this with a dirty (or not) solution.
Did anyone figure out how to do this without having to patch their API server?

*/
```

### `ids`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should be id as it is a belongsTo and will only have one id, thus not being plural ids

@fivetanley
Copy link
Member

I really like the direction this is headed. It seems like a lot of things that were not possible using public APIs are now possible in JavaScript land. I'm wondering what this means in templates though; it seems like it may be a bit cumbersome to get these references yourself every time and define them in a routable component.

API of my dreams:

{{#if comment.isLoaded}}
  your commentID is {{comment.id}}
{{else}}
  <button {{action "load-comment"}}>
    Load comment
  </button>
{{/if}}

With this current RFC, I don't think this is quite possible without always defining isLoaded, etc yourself in every component or every model.

This RFC introduces good primitives; my question for @wycats and @igorT is can we make some nice sugar on top of this in a semver compatible way.

@arenoir
Copy link

arenoir commented Jul 13, 2015

@jdurand I am also looking for a quick fix to accessing foreign keys. Did you have any success?

@jdurand
Copy link

jdurand commented Jul 13, 2015

@arenoir no, I haven't had time to dig into this yet.

@arenoir
Copy link

arenoir commented Jul 13, 2015

@jdurand okay here is my "quick fix". Added overrode the normalizeAttributes hook in the serializer to copy the foreign key. IMO the foreign_key should be public and not be thrown away.

//models/checklist-item.js
export default DS.Model.extend({
  timeEntry: belongsTo('time-entry', {async: true}),
  timeEntryId: attr('string'), //set in serializer
});

//serializers/checklist-item.js
export default DS.ActiveModelSerializer.extend({
  normalizeAttributes(typeClass, hash) {
    var foreignKey = hash['timeEntry'];

    if (foreignKey) {
      hash['timeEntryId'] = foreignKey;
    }

    return this._super(typeClass, hash);
  }
});

I think this a pretty standard use case. Hope this helps.

@sandstrom
Copy link
Contributor

This would be a great addition to Ember Data! ⛵

@wycats do you want to wait for more feedback, or is this RFC ready for activation?

@wycats
Copy link
Member Author

wycats commented Aug 27, 2015

@sandstrom I'm happy with it, assuming it gets further iterated on over time to handle use-cases we missed in the initial design.

@sandstrom
Copy link
Contributor

@wycats Sounds great! I've tried to compile what people have said above (please add if I've missed something).

  • Should mutation be added, or is reading enough for the first version?
  • References ending up in the DOM[1]. As I've understood it this won't happen with this API.
  • Use-case: "Filtering all comments whose id is not equal to 1". Should this be supported? Current proposal doesn't cover this.
  • How will isLoaded be handled? It was said above that Tom and Yehuda would write up an example. Is such an example still needed?

This would be very useful in our app, we're currently using private APIs[2]. I'd rather see a smaller implementation soon, than wait for the utopian RFC covering all use-cases. 😄

Carbon copy: @igorT @wecc @fivetanley


1. Leaking references into DOM

{{! will this leak references? I don't think it will, but please correct me if I'm wrong}}
{{each post.commentReferences as |comment|}}
  {{linkTo 'comment' comment.id}}
{{/each}}

2. Brittle Workaround

// brittle workaround
model._internalModel._relationships.initializedRelationships[relName].canonicalState.length

@sandstrom
Copy link
Contributor

Friendly ping 😄 @igorT @wecc @fivetanley @wycats

This is a great proposal that would solve a concrete pain in our app.

On the checklist above, what are your thoughts? (It's a list of all things mentioned in this thread, I think this proposal is ready for the next stage as soon as you guys feel that they are resolved; can add to the list if something is missing)

@sandstrom
Copy link
Contributor

Should this be closed now, since emberjs/data#3303 is merged?

@fivetanley
Copy link
Member

merged as 074c798. thanks for the reminder @sandstrom!

@fivetanley fivetanley closed this Jan 11, 2016
@fivetanley fivetanley deleted the ember-data-reference-unification branch January 11, 2016 18:23
@pangratz pangratz added the T-ember-data RFCs that impact the ember-data library label Jan 25, 2016
@ef4
Copy link
Contributor

ef4 commented Mar 4, 2016

FYI, I just edited the above original post to make "Rendered" be a valid permalink. It was broken because it pointed at a file under active on master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-ember-data RFCs that impact the ember-data library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants