-
Notifications
You must be signed in to change notification settings - Fork 62
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
Updated to the RC3 standard of JSON API #71
Conversation
The following could be because I'm not following the spec correctly, but humor me. In a case where there are Example: {
"data": {
"type": "myType",
"id": "1",
"name": "myType Name",
"links": {
"self": "/myTypes/1",
"linkOne": {
"self": "/myTypes/1/linkOne",
"linkage": { "type": "subLink", "id": "1" }
}
}
},
"included": [{
"type": "subLink",
"id": "1",
"name": "subLink Name",
"links": {
"self": "/myTypes/1/linkOne",
"linkTwo": {
"self": "/myTypes/1/linkOne/linkTwo",
"linkage": { "type": "otherSubLink", "id": "1" } // <---- Link to another sideloaded record
}
}
}, {
"type": "otherSubLink",
"id": "1",
"name": "otherSubLink Name",
"links": {
"self": "/myTypes/1/linkOne/linkTwo"
}
}]
} Thoughts? |
Hi @green-arrow, I believe your interpretation is correct and I just committed a change that should fix this issue. I also included additional tests to check for this scenario. Thanks for the feedback. |
@eneuhauser I just pulled down your branch with the recent update and it's working beautifully. Tests look good as well. @kurko - is there anything in particular that is stopping this from being merged? |
No. Will review this afternoon!
|
I'm still missing the right Content-Type and Accept header for exchanging data. From the specification:
I suggest overwriting the ajaxOptions: function(url, type, options) {
var hash = this._super(url, type, options);
hash.accepts = {
json: 'application/vnd.api+json'
};
if (hash.data && type !== 'GET') {
hash.contentType = 'application/vnd.api+json';
}
return hash;
} Updated my comment to include the Accept header |
Additional comment in regards to findBelongsTo: function(store, record, url, relationship) {
var related = record[relationship.key];
// FIXME Without this, it was making unnecessary calls, but cannot create test to verify.
if(related) { return; }
return this.ajax(url, 'GET');
} Due to this Example model: export default DS.Model.extend({
vitals: DS.belongsTo('vitals', { async: true })
}); When trying to |
Additional issue that I ran across: specifying an empty array for the root When extractArrayData: function(data, payload) {
var type = data.length > 0 ? data[0].type : null, serializer = this;
data.forEach(function(item) {
if(item.links) {
serializer.extractRelationships(item.links, item);
//delete data.links;
}
});
payload[type] = data;
} If no data is present, we punt and say the
|
…s, and removing findBelongsTo override.
@jonkoops, I added 'application/vnd.api+json' in the list of accept headers and set the content type for non-GET requests. Both of these are overridable as properties in the adapter without having to override the whole ajaxOptions method. @green-arrow, I've fixed the empty array issue. I also removed my override of findBelongsTo. I'm not seeing the extra requests I use to, so some other logic must have fixed that. |
@eneuhauser Looks good to me 👍 |
@eneuhauser awesome. Additional question. The spec says that you could include a query param Thoughts? |
@green-arrow, if you look at the compound-document-test, that's the use case it's validating. The test case ensures that regardless if the relationship is marked as async true or false, if a relationship is returned in the This is the case when you do |
@eneuhauser gotcha. I will have to do some digging on my end then, because I am seeing more calls executed even though the |
@eneuhauser is this supposed to fire API calls when |
@joshsmith @eneuhauser stated that API calls should not be fired in this case if they've already been loaded via the |
@joshsmith, the app will fire API calls when calling @green-arrow, I'm not sure if you're still having your issue with having extra calls, but I had seen that once before, which is why I use to have the |
@eneuhauser the following prevents duplicate requests:
findBelongsTo: function(store, snapshot, url, relationship) {
if(snapshot.belongsTo(relationship.key)) { return; }
return this._super(store, snapshot, url, relationship);
} Note: This is using It seems to me, though, that this behavior should be native to ember-data and not something that the |
I think I've narrowed it down a bit more, but now I'm stuck. In ember-data, there is the following code: BelongsToRelationship.prototype.getRecord = function() {
//TODO(Igor) flushCanonical here once our syncing is not stupid
if (this.isAsync) {
var promise;
if (this.link) {
var self = this;
promise = this.findLink().then(function() {
return self.findRecord();
});
} else {
promise = this.findRecord();
}
return PromiseObject.create({
promise: promise,
content: this.inverseRecord
});
} else {
Ember.assert("You looked up the '" + this.key + "' relationship on a '" + this.record.constructor.typeKey + "' with id " + this.record.get('id') + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", this.inverseRecord === null || !this.inverseRecord.get('isEmpty'));
return this.inverseRecord;
}
}; The issue is that In if(id) {
resource[link] = id;
} If I change that block to the following, additional requests are not made: if(id) {
resource[link] = id;
delete resource.links[link];
} As far as I can tell, this doesn't seem to have any adverse side effects. I have not pulled down the source and run the tests though. Could someone try what I have above and see if all tests pass? I would do that myself but I have to hop off for a while to attention my kids 😄 |
Polymorphic relationships are broken with this because the function getLinkageId(linkage) {
if(Ember.isEmpty(linkage)) { return null; }
return (Ember.isArray(linkage)) ? getLinkageIds(linkage) : {type: Ember.String.singularize(linkage.type), id: linkage.id};
}
function getLinkageIds(linkage) {
if(Ember.isEmpty(linkage)) { return null; }
var ids = [], index, total;
for(index=0, total=linkage.length; index<total; ++index) {
ids.push({type: Ember.String.singularize(linkage[index].type), id: linkage[index].id});
}
return ids;
} |
By adding the findBelongsTo: function(store, snapshot, url, relationship) {
if(snapshot.belongsTo(relationship.key)) { return; }
return this._super(store, snapshot, url, relationship);
},
findHasMany: function(store, snapshot, url, relationship) {
if(snapshot.hasMany(relationship.key).get('length')) { return []; }
return this._super(store, snapshot, url, relationship);
} |
Unfortunately, none of these pass the tests. @green-arrow, by definition of the model, @tobscure, If you could send me a sample of your response, I can see if I could duplicate the problem. |
@eneuhauser that's not correct. http://emberjs.com/api/data/classes/DS.Snapshot.html#method_belongsTo
I was not aware that the link was used for other things. In that case, it seems that there is a bug in ember-data in the method I posted above. It seems like Maybe @mixonic or somebody else familiar with ember-data could chime in on that? |
@eneuhauser Given a polymorphic relationship setup like this: App.Activity = DS.Model.extend({
subject: DS.belongsTo('subject', {polymorphic: true})
});
App.Subject = DS.Model.extend();
App.Post = App.Subject.extend();
App.Discussion = App.Subject.extend(); And a JSON-API response like this:
Currently, this serializer is normalizing the payload to this:
Which causes Ember Data to freak out because it doesn't know which model type the relationship is to. Instead, my code normalizes it to:
Which fixes the problem. It was a quick fix; it shouldn't include the type if it's not a polymorphic relationship (and I'm guessing that's the cause of the failed tests). |
Note: npm source for ember-json-api changed to a fork, but I still had to apply a custom change to get polymorphic relationships to work (see kurko/ember-json-api#71 (comment))
The code I had for findHasMany: function(store, snapshot, url, relationship) {
if(snapshot.hasMany(relationship.key).get('length')) { return []; }
return this._super(store, snapshot, url, relationship);
} The next method called is The root of this problem seems to be the prototypes for |
Sorry for spamming this PR, but I did manage to find a super hacky workaround for findHasMany: function(store, snapshot, url, relationship) {
if(snapshot.hasMany(relationship.key).get('length')) { return new Ember.RSVP.Promise((resolve, reject) => reject()); }
return this._super(store, snapshot, url, relationship);
} In all, my application adapter looks like this, and I'm not seeing any extra requests being made for data loaded via the import Ember from 'ember';
import JsonApiAdapter from 'ember-json-api/json-api-adapter';
import ENV from '../../config/environment';
export default JsonApiAdapter.extend({
host: ENV.APP.adapter.host,
namespace: ENV.APP.adapter.namespace,
findBelongsTo: function(store, snapshot, url, relationship) {
if(snapshot.belongsTo(relationship.key)) { return; }
return this._super(store, snapshot, url, relationship);
},
findHasMany: function(store, snapshot, url, relationship) {
if(snapshot.hasMany(relationship.key).get('length')) { return new Ember.RSVP.Promise((resolve, reject) => reject()); }
return this._super(store, snapshot, url, relationship);
}
}); |
@tobscure how are you making polymorphic relationships work with this serializer? It seems like polymorphic support was explicitly removed by @eneuhauser /**
* Use "links" key, remove support for polymorphic type
*/
serializeBelongsTo: function(record, json, relationship) {
var attr = relationship.key;
var belongsTo = record.belongsTo(attr);
var type = this.keyForRelationship(relationship.type.typeKey);
var key = this.keyForRelationship(attr);
if (isNone(belongsTo)) return;
json.links = json.links || {};
json.links[key] = belongsToLink(key, type, get(belongsTo, 'id'));
} To clarify, I have a polymorphic relationship defined, but ember-data is not pushing anything to the store. If I change the |
Thank you for all the work on this! This is exactly the solution I've been looking for, for the errors I've been running into 😄 |
@eneuhauser Seems like issue #3 is a blocking issue in specification compliance. |
@jonkoops I submitted a PR to @eneuhauser implementing the PUT/PATCH swap needed for specification compliance: eneuhauser#6 |
Ok, so unless someone comes shouting and saying this is not working, I'm merging this tonight and releasing a new version 😄 |
👍 👍 👍 Yay! |
Awesome! |
Awesome, thanks! There are 3 issues reported in my repository that I haven't had a chance to look at yet. Additionally, I'm working on the findHasMany issue. I'm hoping to have time tomorrow to work on them. If you merge the current pull request, I can submit separate pull requests to solve those issues. Edit: After looking at the issues, I don't think there is anything to fix. The findHasMany is the only open issue. |
@eneuhauser Thanks for your hard work on this. And @kurko of course. As an open source project maintainer myself, I know these hours sometimes go unnoticed. Much appreciated. |
I think we should get eneuhauser#8 fixed first, it's a minor issue but it could cause some confusion. |
I've made some comments in issue#8. Would love some feedback if I should merge my fix. |
Thanks for your great work on this @eneuhauser. We've been using your branch for some time now and I haven't run into any big issues so far. |
@kurko In my opinion we should get this merged, @eneuhauser anything blocking in your opinion? |
@jonkoops and @kurko, I think RC3 is good to go. There will be more changes before 1.0 hits. Someone already opened Issue 10 about a change since RC3. Since ember-json-api is one of the de facto implementations of JSON API, I think it would be a good idea to keep up with the release candidates. I can begin work on that issue, but until another release candidate hits or 1.0, I'm not going to merge it in. |
@eneuhauser Based on the latest RC3 spec, there is an attributes field that hold all of the model fields, is there any plan on updating this PR to support the final revision RC3? Edit: Keep it up! |
👍 on getting this merged |
Folks, I'm merging this soon. I'm on vacation and without computer. Let me
|
Updated to the RC3 standard of JSON API
😄 Now, would someone take the torch for RC4? Seems pretty straightforward |
Thanks for merging! I have been heads down on a few non-Ember projects, but I am days away from a vacation. I should have some downtime to update to RC4. Someone has already submitted a pull request into my repo. I'll also look into upgrading Ember and Ember Data versions. According to the status page, JSON API 1.0 is slated for tomorrow. That will get some consistencies in implementations to get everyone on the same page. |
For the record: The latest developments are in eneuhauser#14. I'm using it in my app and seems to work fine 👍 |
Per JSON API RC3 release, the spec is close to being finalized. Now there is a line in the sand, it's easy to build against the RC3 standard until either another release candidate or 1.0 is ratified. The main feature that this pull request supports that #68 does not is the consistent linkage change, where a linked resource will have a
linkage
property that includes thetype
andid
. The serializer is not backwards compatible and only works with the RC3 standard.One concept of JSON API I have not been able to support is the
self
link. The current interface for the adapter does not allow accessing the owner record when doing acreateRecord
orupdateRecord
. I'm storing theself
link within the resource's links, but there currently isn't a way to access it.On the current project I'm working on, I have updated my server to be compliant with the RC3 standard and this adapter and serializer is working well.