如何使嵌入的 hasMany 关系与 ember 数据一起使用
Posted
技术标签:
【中文标题】如何使嵌入的 hasMany 关系与 ember 数据一起使用【英文标题】:How to make embedded hasMany relationships work with ember data 【发布时间】:2012-12-28 13:25:25 【问题描述】:我无法让 embedded
hasMany
正确处理 ember 数据。
我有这样的事情
App.Post = DS.Model.extend(
comments: DS.hasMany('App.Comment')
);
App.Comment = DS.Model.extend(
post: DS.hasMany('App.Post'),
name: attr('string')
);
我的 API 为 GET /post
返回以下内容:
[
id: 1
comments: [name: 'test', name: 'test2']
,
...
]
我需要用POST /post
发送这个:
[
comments: [name: 'test', name: 'test2']
,
...
]
我想使用 Ember 模型并让他们提出适当的请求:
var post = App.store.createRecord(App.Post, hash_post_without_comments);
post.get('comments').createRecord(hash_comment);
App.store.commit(); // This should call the POST api
和
var posts = App.store.find(App.Post); // This should call the GET api
当我尝试post: DS.hasMany('App.Post', embedded: true)
之类的方法时,GET 正在工作,但 POST 正在尝试为这两条记录创建一个 POST,而不仅仅是父记录。
编辑:我的真实用例
1- 我刚刚从 master 构建了 ember 数据
2- 我的适配器:RESTAdapter
3- 序列化器:JSONSerializer
4- 我添加了
App.MyAdapter.map('App.Join',
columns: embedded: 'always'
);
5- 我的模型是:
App.Join = DS.Model.extend(
rowCount: DS.attr('number'),
columns: DS.hasMany('App.JoinColumn'),
);
App.JoinColumn = DS.Model.extend(
join: DS.belongsTo('App.Join')
);
6- 时间:
var a = App.Join.find(1);
a.get('columns').createRecord();
App.store.commit();
连接列的 POST 已发送且父级不脏
我错过了什么?
【问题讨论】:
还有其他人阅读这篇文章,看看:vinay.io/static/blog/2013/12_17.html 【参考方案1】:这对我有用(Ember 1.5.1+pre.5349ffcb,Ember Data 1.0.0-beta.7.f87cba88):
App.Post = DS.Model.extend(
comments: DS.hasMany('comment', embedded: 'always' )
);
App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin,
attrs:
comments: embedded: 'always'
);
【讨论】:
【参考方案2】:为此添加更新,以防其他人看到此帖子并且很难弄清楚当前版本的 ember-data 的适用范围。
从 Ember Data 1.0.0.beta.7 开始,您需要覆盖序列化程序上的相应方法。这是一个例子:
1) 重新打开序列化程序(感谢this post):
DS.RESTSerializer.reopen(
serializeHasMany: function(record, json, relationship)
var hasManyRecords, key;
key = relationship.key;
hasManyRecords = Ember.get(record, key);
if (hasManyRecords && relationship.options.embedded === "always")
json[key] = [];
hasManyRecords.forEach(function(item, index)
// use includeId: true if you want the id of each model on the hasMany relationship
json[key].push(item.serialize( includeId: true ));
);
else
this._super(record, json, relationship);
);
2) 将embedded: 'always'
选项添加到模型上的关系中:
App.Post = DS.Model.extend(
comments: DS.hasMany('comment',
embedded: 'always'
)
);
【讨论】:
【参考方案3】:在 master 上,正确的 API 是:
App.Adapter.map('App.Post',
comments: embedded: 'always'
);
embedded
的两个可能值是:
load
:加载时嵌入子记录,但应保存为独立记录。为此,子记录必须有一个 ID。
always
:子记录在加载时嵌入,并保存嵌入在同一记录中。这当然会影响记录的脏度(如果子记录发生更改,适配器会将父记录标记为脏)。
如果没有自定义适配器,可以直接在DS.RESTAdapter
上调用map
:
DS.RESTAdapter.map('App.Post',
comments: embedded: 'always'
);
【讨论】:
belongsTo 也一样吗? 是的。它与嵌入式 belongsTo 的 API 相同。 我认为持久化嵌入记录时可能存在错误,github.com/emberjs/data/pull/578 @YehudaKatz,随着对 ember-data 的新修订,通过自定义适配器映射的正确方法是什么? Adapter.map 函数不再存在。 我认为,我们必须遵循这个 JSON 约定。嵌入对象跟随主要对象。 emberjs.com/guides/models/connecting-to-an-http-server/…【参考方案4】:我也有同样的问题。
此错误已在 ember 数据问题跟踪器上报告。 以下 PR 添加了 2 个失败的测试来显示问题:https://github.com/emberjs/data/pull/578
目前似乎没有解决方法。
编辑:
sebastianseilund 2 天前打开了一个 PR,它解决了您的问题。 看看:https://github.com/emberjs/data/pull/629/files
【讨论】:
以上是关于如何使嵌入的 hasMany 关系与 ember 数据一起使用的主要内容,如果未能解决你的问题,请参考以下文章
Ember js - 更新其他表后 Hasmany 关系中断
Ember.js:重新加载通过有效负载中的“链接”给出的 .hasMany 关系
用于从 hasMany 关系中检索一条记录的 Ember 计算属性?
Ember 数据:为啥 hasMany 和 belongsTo