问题
I have a few models in Rails that look something like this:
class Issue < ActiveRecord::Base
belongs_to :reporter, class_name: 'User'
belongs_to :assignee, class_name: 'User'
has_many :comments
end
class User < ActiveRecord::Base
end
class Comment < ActiveRecord::Base
end
with serializers like so:
class IssueSerializer < ActiveModel::Serializer
attributes :id
embed :ids, include: true
has_one :reporter, :embed => :ids
has_one :assignee, :embed => :ids
end
class UserSerializer < ActiveModel::Serializer
attributes :id, :name
end
class CommentSerializer < ActiveModel::Serializer
attributes :id, :body
end
This produces JSON that looks something like the following:
{
"issues": [
{
"id": 6,
"reporter_id": 1,
"assignee_id": 2,
"comment_ids": [
3
]
},
],
"comments": [
{
"id": 3
"body": "Great comment"
}
],
"reporters": [
{
"id": 1
"name": "Ben Burton"
}
],
"assignees": [
{
"id": 2
"name": "Jono Mallanyk"
}
]
}
The problem is that the side-loaded reporters and assignees JSON objects aren't recognized by Ember as User objects, and I see the following error:
Uncaught Error: assertion failed: Your server returned a hash with the key reporters but you have no mapping for it
I don't want to remove
embed :ids, include: true
from my IssueSerializer, because then the comments wouldn't be serialized.
There are a few potential ways to solve this that I've considered:
- If the embed method for ActiveModel::Serializer accepted a list of models in its include option, this could filter the JSON response to only include side-loaded comments.
- Ember data's model could be configured to side load users from "users", "reporters" and "assignees"... but as far as I can tell from the source it only appears to support one key for sideloadAs.
- Somehow ignore/disable side-loading errors for unknown keys (probably the least sane approach).
Is there another option I'm missing here? I think I may have to write a fix and submit a pull request to either rails-api/active_model_serializers, emberjs/data, or both.
EDIT: My temporary workaround for this is to change the IssueSerializer to only serialize the ids for reporter and assignee:
class IssueSerializer < ActiveModel::Serializer
attributes :id, :reporter_id, :assignee_id
embed :ids, include: true
has_many :comments, :embed => :ids
end
回答1:
I had similar problem and have found solution at ActiveModel::Serializers readme. You can use :root
option. Try something like this for issue serializer:
class IssueSerializer < ActiveModel::Serializer
attributes :id
embed :ids, include: true
has_one :reporter, :root => "users"
has_one :assignee, :root => "users"
has_many :comments
end
回答2:
You should read this page. The section of Revision 12 explains about the sideloading of data of the same type:
Now, homeAddress and workAddress will be expected to be sideloaded together as addresses because they are the same type. Furthermore, the default root naming conventions (underscore and lowercase) will now also be applied to sideloaded root names.
Your Model should be like:
App.Issue = DS.Model.extend({
reporter: DS.belongsTo('App.User'),
assignee: DS.belongsTo('App.User'),
comments: DS.hasMany('App.Comment')
});
The JSON Result should have a key for the users:
{
"issues": [
{
"id": 6,
"reporter_id": 1,
"assignee_id": 2,
"comment_ids": [
3
]
},
],
"comments": [
{
"id": 3
"body": "Great comment"
}
],
"users": [
{
"id": 1
"name": "Ben Burton"
},{
"id": 2
"name": "Jono Mallanyk"
}
]
}
Because you configured in your Model that the reporter
is of type User
, Ember search for a user in the result.
回答3:
I was having the same issue, adding include: false
on the association did the trick for me.
embed :ids, include: true
attributes :id, :title
has_many :domains, key: :domains, include: false
has_many :sessions, key: :sessions
来源:https://stackoverflow.com/questions/15363333/side-loading-objects-with-non-standard-class-names-in-emberjs-with-railsactive