Javascript 如何在 ember-data 模型中表示数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12168570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to represent arrays within ember-data models?
提问by dechov
Is it necessary to use DS.hasMany
pointing to a DS.Model
when a model contains an array? Even if the array elements are not really models (no IDs or endpoints of their own)? Is there a better way?
当模型包含数组时是否需要使用DS.hasMany
指向 a DS.Model
?即使数组元素不是真正的模型(没有自己的 ID 或端点)?有没有更好的办法?
I am using DS.hasMany
, but my extended DS.RESTAdapter
is throwing me a 404 trying to access the model, even though I'm never calling find
on it, and hasMany
is called with { embedded: true }
. I am seeing this error for the first time (apparently in connection with this model, since it goes away without it):
我正在使用DS.hasMany
,但我的扩展DS.RESTAdapter
向我抛出 404 试图访问模型,即使我从不调用find
它,并且hasMany
使用{ embedded: true }
. 我第一次看到这个错误(显然与这个模型有关,因为没有它它就会消失):
Uncaught Error: assertion failed: Emptying a view in the inBuffer state is not allowed and should not happen under normal circumstances. Most likely there is a bug in your application. This may be due to excessive property change notifications. ember-latest.js:43
What does this mean and what might be causing it?
这是什么意思,可能是什么原因造成的?
Here's the stack trace:
这是堆栈跟踪:
Ember.assert ember-latest.js:43
Ember.View.states.inBuffer.empty ember-latest.js:13644
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.CollectionView.Ember.ContainerView.extend.arrayWillChange ember-latest.js:14477
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
Ember.Array.Ember.Mixin.create.arrayContentWillChange ember-latest.js:6963
Ember.ArrayProxy.Ember.Object.extend.arrangedContentArrayWillChange ember-latest.js:9281
Ember.ArrayProxy.Ember.Object.extend._arrangedContentWillChange ember-latest.js:9235
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyBeforeObservers ember-latest.js:2016
propertyWillChange ember-latest.js:2594
iterDeps ember-latest.js:2077
dependentKeysWillChange ember-latest.js:2092
propertyWillChange ember-latest.js:2592
set ember-latest.js:1416
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3145
Map.forEach ember-latest.js:1273
OrderedSet.forEach ember-latest.js:1145
Map.forEach ember-latest.js:1271
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3128
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyObservers ember-latest.js:1999
propertyDidChange ember-latest.js:2632
Ember.Observable.Ember.Mixin.create.propertyDidChange ember-latest.js:7917
Ember.Observable.Ember.Mixin.create.notifyPropertyChange ember-latest.js:7930
didChangeData ember-data-latest.js:2053
Ember.StateManager.Ember.State.extend.sendRecursively ember-latest.js:15446
Ember.StateManager.Ember.State.extend.send ember-latest.js:15431
DS.Model.Ember.Object.extend.send ember-data-latest.js:3058
DS.Store.Ember.Object.extend.load ember-data-latest.js:1737
DS.Store.Ember.Object.extend.loadMany ember-data-latest.js:1763
embeddedFindRecord ember-data-latest.js:3434
hasAssociation ember-data-latest.js:3459
ComputedPropertyPrototype.get ember-latest.js:2968
get ember-latest.js:1362
getPath ember-latest.js:1484
get ember-latest.js:1355
getWithGlobals ember-latest.js:4041
Binding.connect ember-latest.js:4140
connectBindings ember-latest.js:4600
finishPartial ember-latest.js:4610
Class ember-latest.js:8315
Ember.Mixin.create.create ember-latest.js:8457
Ember.View.Ember.Object.extend.createChildView ember-latest.js:13179
Ember.View.states.inBuffer.appendChild ember-latest.js:13622
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
program2
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember._HandlebarsBoundView.Ember._MetamorphView.extend.render ember-latest.js:18075
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
bind ember-latest.js:18129
(anonymous function) ember-latest.js:18199
(anonymous function) ember-latest.js:18271
program1
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19624
(anonymous function) ember-latest.js:18167
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.Ember.Object.extend.createElement ember-latest.js:12669
Ember.View.states.preRender.insertElement ember-latest.js:13558
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
invoke ember-latest.js:3428
iter ember-latest.js:3475
RunLoop.flush ember-latest.js:3531
RunLoop.end ember-latest.js:3447
Ember.run.end ember-latest.js:3639
autorun ember-latest.js:3705
Thanks for any help.
谢谢你的帮助。
Update:This fiddleworks (with example from docs), but how could those objects be represented if the tags aren't real models (i.e. don't have IDs)?
回答by Jorgeblom
Well... It was a little bit difficult but mixing all answers in this post I made it work.
嗯......这有点困难,但在这篇文章中混合了所有答案,我使它起作用。
Firstly, you should create a transform for the new type "array":
首先,您应该为新类型“数组”创建一个转换:
DS.ArrayTransform = DS.Transform.extend({
deserialize: function(serialized) {
return (Ember.typeOf(serialized) == "array")
? serialized
: [];
},
serialize: function(deserialized) {
var type = Ember.typeOf(deserialized);
if (type == 'array') {
return deserialized
} else if (type == 'string') {
return deserialized.split(',').map(function(item) {
return jQuery.trim(item);
});
} else {
return [];
}
}
});
App.register("transform:array", DS.ArrayTransform);
Now, in your model, just use it as another attr:
现在,在您的模型中,只需将其用作另一个属性:
App.myModel = Ember.Model.extend({
name : DS.attr('string'),
cont : DS.attr('array')
}
And we are done. Remember, when adding elements to the array, to use pushObject.
我们已经完成了。请记住,向数组添加元素时,要使用 pushObject。
In a controller:
在控制器中:
this.get('model.cont').pushObject('new Item');
I hope this helps someone.
我希望这可以帮助别人。
回答by Shreyans
I use a raw
transform, which looks like this in ember-data revision 11:
我使用了一个raw
转换,它在 ember-data 修订版 11 中看起来像这样:
DS.RESTAdapter.registerTransform('raw', {
deserialize: function(serialized) {
return serialized;
},
serialize: function(deserialized) {
return deserialized;
}
});
Then, within a model, I do this:
然后,在模型中,我这样做:
App.MyModel = Ember.Model.extend({
anArray: DS.attr('raw')
});
and can use anArray
like a regular array anywhere.
并且可以anArray
像常规数组一样在任何地方使用。
回答by Mayank Patel
Here is an example of creating a custom array type in Ember-Data (version 10):
以下是在 Ember-Data(版本 10)中创建自定义数组类型的示例:
DS.JSONTransforms.array =
# If the outgoing json is already a valid javascript array
# then pass it through untouched. In all other cases, replace it
# with an empty array. This means null or undefined values
# automatically become empty arrays when serializing this type.
serialize: (jsonData)->
if Em.typeOf(jsonData) is 'array' then jsonData else []
# If the incoming data is a javascript array, pass it through.
# If it is a string, then coerce it into an array by splitting
# it on commas and trimming whitespace on each element.
# Otherwise pass back an empty array. This has the effect of
# turning all other data types (including nulls and undefined
# values) into empty arrays.
deserialize: (externalData)->
switch Em.typeOf(externalData)
when 'array' then return externalData
when 'string' then return externalData.split(',').map((item)-> jQuery.trim(item))
else return []
Now you can use the custom type in a model attribute:
现在您可以在模型属性中使用自定义类型:
App.CalenderWeek = DS.Model.extend
selected_days = DS.attr('array')
And now when you fetch a record with:
现在,当您使用以下方法获取记录时:
App.CalendarWeek.find(1)
both of these incoming json records will deserialize correctly into an Array:
这两个传入的 json 记录都将正确反序列化为一个数组:
{ selected_days: ['Monday', 'Tuesday', 'Saturday'] }
or
或者
{ selected_days: 'Monday, Tuesday, Saturday' }
回答by Ryan
In Ember Data 1.0.0 Beta, one has been given the ability to "register" his or her custom transform "subclass". I'd prefer to refer to it as an extended DS.Transform
object.
在Ember Data 1.0.0 Beta 中,人们可以“注册”他或她的自定义变换“子类”。我更愿意将它称为扩展DS.Transform
对象。
DS.ArrayTransform = DS.Transform.extend({
deserialize: function(deserialized) {
// ...
return deserialized;
},
serialize: function(serialized) {
// ...
return serialized;
}
});
App.register('transform:array', DS.ArrayTransform);
回答by Mike Aski
If you absolutely need a custom data structure to be exchanged with your server, you can enrich DS.attr.transforms
and declare a new array
codec, for example.
例如,如果您绝对需要与服务器交换自定义数据结构,则可以丰富DS.attr.transforms
和声明新的array
编解码器。
See source codefor existing attribute codecs implementation. It is a good place to start adding your own.
请参阅现有属性编解码器实现的源代码。这是开始添加自己的好地方。
回答by Devin G Rhode
Interestingly all the other 4 answers to this question have almost identical deserialize and serialize functions, so you could simplify things down to:
有趣的是,这个问题的所有其他 4 个答案都具有几乎相同的反序列化和序列化功能,因此您可以将事情简化为:
import Em from 'ember'
import DS from 'ember-data'
# Presumably based on these answers: http://stackoverflow.com/questions/12168570/how-to-represent-arrays-within-ember-data-models
# All we need to do is always make sure an array is returned from serialize or deserialize
toArray = (data) ->
switch Em.typeOf(data)
when 'array' then data
when 'string' then JSON.parse(data)
else []
export default DS.Transform.extend
deserialize: toArray
serialize: toArray
This is using ember-cli-coffees6for coffeescript with import/export
support
这是使用ember-cli-coffees6来import/export
支持咖啡脚本
回答by xiaolingxiao
A bit late to the game here but here's a jFiddle I found that is a simple implementation of declaring a new array codec
这里的游戏有点晚了,但我发现这是一个 jFiddle,它是声明新数组编解码器的简单实现