我想为父母和孩子之间的关系以及理想的json结构以及路线和控制器的基本示例一劳永逸地记录(并保留永久记录!)。
当我(希望)得到答案和评论时,我会更新问题以反映最佳实践。
所以,我有我的余烬模型:
App.Customer = DS.Model.extend({
name: DS.attr('string' ),
orders: DS.hasMany("order")
});
App.Order = DS.Model.extend({
carrier: DS.attr('string' ),
customer: DS.belongsTo("customer")
orderlines: DS.hasMany("orderline")
});
App.Orderline = DS.Model.extend({
order: DS.belongsTo("order"),
item: DS.belongsTo("item"),
price: DS.attr('number'),
qty: DS.attr('number'),
});
App.Item = DS.Model.extend({
name: DS.attr('string'),
orderlines: DS.hasMany("orderline")
});
问题1:这些模型定义是否正确?
我可以采用多种方法来查看这些数据:
问题2:
每个路由器/控制器需要哪些?
我有选项2)工作到显示客户,但当我点击客户的订单链接时,我收到所有订单。可能是我的json错了..或者更有可能我不知道如何显示所选客户的所有订单。或者两者:(
我目前有:
{"customers":[
{"name":"foobar inc","id":"0x181","orders":["0x386","0x3a4"]},
{"name":"barfoo ltd","id":"0x182","orders":["0x3de","0x3fd"]} ],
"orders":[
{"carrier":"Standard Mail","id":"0x386","customer_id":"0x181"},
{"carrier":"FlyByNight Courier","id":"0x3a4","customer_id":"0x181"},
{"carrier":"Standard Mail","id":"0x3de","customer_id":"0x182"},
{"carrier":"FlyByNight Courier","id":"0x3fd","customer_id":"0x182"} ]}
问题3:这是正确的吗? (我可以让json以任何格式出现,因此最好创建最适合ember-data的json结构)。
问题4:此时我是否应该包含相关数据(所有客户,所有订单,所有订单)?或者最好不要包含子数据,但是从服务器上获取这些数据?
我现在就把它留下来 - 希望我能尽快开始理解嵌套数据!感谢。
答案 0 :(得分:2)
问题1 这些模型定义对我来说很好。
问题2 您可能希望最终混合使用您的选项#1和#2。选项卡可让您查看每个模型的完整列表,但能够在/customers
页面上按层次结构向下钻取。您需要的确切路线取决于您希望在应用中提供的确切网址,这些网址与您要显示的屏幕/视图相对应。
假设你想要这些网址/屏幕
/customers
- 所有客户的列表
/customers/1
- 有关客户#1的详细信息
/customers/1/orders
- 客户#1的所有订单
/customers/1/orders/1
- 订单#1的详细信息(包括OrderLine
s)
然后您的路线将是:
App.Router.map(function() {
this.resource('customers');
this.resource('customer', { path: '/customers/:customer_id' }, function(){
this.resource('orders');
this.resource('order', { path: '/orders/:order_id'});
});
});
问题3 是的,JSON看起来是正确的。
问题4 这取决于您的应用的需求。您可能不希望在单个请求中包含整个数据树(Customers - > Orders - > OrderLines - > Items)。您可能希望在用户离开树时逐步加载内容。
例如,您首先要加载客户列表,然后当用户点击客户时,您需要触发请求以获取该客户的所有订单。等等,在树下。
这是一个显示一般概念的JSBin:http://jsbin.com/ucanam/1074/edit
请注意,hasMany
关系是使用{async:true}
定义的。这允许按需查找它们,而不是使用父模型加载。
如果您切换到RESTAdapter
,当它尝试加载客户的订单列表时,它会发出如下请求:
/orders?ids[]=0x3de&ids[]=0x3fd
[更新]:回应评论。
因此,对于您请求的网址结构:> >客户列表> - >客户详细信息> - >订单清单> - >订单详情> - >订单行列表> - >订单行详细信息
你与JSBin非常接近。绊倒你的是模板嵌套的工作方式。
'order'
模板(如果存在)将针对符合/orders/xxx
或/orders/xxx/*
的所有路线呈现。如果路线的其他部分(例如/orderlines
)会将这些模板渲染到'order'
模板中。但是,由于您的'order'
模板没有{{outlet}}
,因此'orderlines'
模板无需渲染。
这是一个稍微修改过的JSBin:http://jsbin.com/iKIsisO/3/edit
唯一的变化是在{{outlet}}
模板的底部添加了'order'
。
现在,在主要订单明细内部下方呈现orderlines
可能不是您想要的。您最有可能希望订单行替换其他订单信息。在这种情况下,您可以将'order'
模板重命名为'order/index'
。 (您也可以从OrderRoute
删除needs
和OrderController
。
另一个JSBin,模板重命名为:http://jsbin.com/iDiMOCO/1/edit
以Order
模型为例,当您访问/orders
路由以及适用于该集合的任何其他路由(/orders/new
,/orders/some_custom_batch_thing
)时,如果主'orders'
模板存在,则呈现该主模板,然后将子路径模板呈现为'orders'
。如果'orders'
模板不存在,则子路径模板将呈现到链中的{{outlet}}
。 /orders
路由是一种特殊情况,因为它的子模板被隐式假设为orders/index
。同样,对于/orders/xxx
以及适用于单个Order
的任何其他路由,首先呈现'order'
模板(如果存在),然后将子路径模板呈现为'order'
,或最直接的父{{outlet}}
。另外,使用/orders/xxx
'order/index'
模板是隐式子路径模板。
/orders
:: 'orders'
- > 'orders/index'
/orders/new
:: 'orders'
- > 'orders/new'
/order/xxx
:: 'order'
- > 'order/index'
/orders/xxx/edit
:: 'order'
- > 'order/edit'
因此,'orders'
和'order'
模板实际上类似于每个模型布局模板,可用于以一致的方式装饰子路径。
最终的JSBin,在模板中呈现模板名称,并添加一些额外的模板作为“模型布局”:http://jsbin.com/iKIsisO/2/edit
我希望一切都有道理。