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 o
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
http://jsfiddle.net/Nook/ab2Xf/
Here is an example of creating a custom array type in Ember-Data (version 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:
{ selected_days: ['Monday', 'Tuesday', 'Saturday'] }
or
{ selected_days: 'Monday, Tuesday, Saturday' }
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.
In a controller:
this.get('model.cont').pushObject('new Item');
I hope this helps someone.
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.
See source code for existing attribute codecs implementation. It is a good place to start adding your own.
I use a raw
transform, which looks like this in ember-data revision 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.
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.
DS.ArrayTransform = DS.Transform.extend({
deserialize: function(deserialized) {
// ...
return deserialized;
},
serialize: function(serialized) {
// ...
return serialized;
}
});
App.register('transform:array', DS.ArrayTransform);