How to add objects to a hasMany relationship with ember data

George Eracleous picture George Eracleous · Dec 22, 2012 · Viewed 17.7k times · Source

I have these two models:

App.Items = DS.Model.extend({
    provider: DS.attr('string'),
    name: DS.attr('string'),
    description: DS.attr('string'),
});

App.Baskets = DS.Model.extend({
    selectedItems: DS.hasMany('App.Items'),
    name: DS.attr('string'),
    username: DS.attr('string'),
})

Now what I want to do is add a new Item to a Basket when a user selects it. I have tried to do this:

basket = App.Baskets.find(1);
item = App.Items.find(1);
basket.set("selectedItems", item)  ; 
App.store.commit();

This doesn't return any errors but it doesn't trigger any requests to the server.

Alternatively, I have tried this:

basket = App.Baskets.find(1);
selectedItems = basket.get("selectedItems")
selectedItems.pushObject(App.Items.find(1))
App.store.commit();

This method returns an error:

Uncaught TypeError: Cannot call method 'indexOf' of undefined ember.js:1691
get ember.js:1691
DS.OneToManyChange.sync ember-data.js:4572
(anonymous function) ember-data.js:424
OrderedSet.forEach ember.js:1410
DS.ManyArray.DS.RecordArray.extend.arrayContentDidChange ember-data.js:423
newFunc ember.js:1167
Ember.ArrayProxy.Ember.Object.extend.arrangedContentArrayDidChange ember.js:10600
sendEvent ember.js:3792
Ember.Array.Ember.Mixin.create.arrayContentDidChange ember.js:7933
Ember.Mixin.create.replace ember.js:11011
Ember.ArrayProxy.Ember.Object.extend.replaceContent ember.js:10476
DS.ManyArray.DS.RecordArray.extend.replaceContent ember-data.js:351
newFunc ember.js:1167
Ember.ArrayProxy.Ember.Object.extend.replace ember.js:10591
Ember.MutableArray.Ember.Mixin.create.insertAt ember.js:8398
Ember.MutableArray.Ember.Mixin.create.pushObject ember.js:8450
App.Router.Ember.Router.extend.root.Ember.Route.extend.items.Ember.Route.extend.savePreferences dashboard-app.js:218
sendRecursively ember.js:17303
sendEvent ember.js:17320
Ember.StateManager.Ember.State.extend.send ember.js:17845
ActionHelper.registeredActions.(anonymous function).handler ember.js:22673
(anonymous function) ember.js:13009
Ember.handleErrors ember.js:379
(anonymous function) ember.js:13003
v.event.dispatch jquery.min.js:2
o.handle.u

The weird things is that when I try to set a normal attribute of the same model, let's say set the name of the basket, everything works fine. Ember data fires a PUT request to the server and my model is updated. So obviously then problem is when I update a relationship. Am I doing this the wrong way or is it an ember data bug?

Answer

Bradley Priest picture Bradley Priest · Dec 23, 2012

Your code is failing because in the current version of Ember Data you have to specify an inverse to every relationship.

App.Item = DS.Model.extend({
    provider: DS.attr('string'),
    name: DS.attr('string'),
    description: DS.attr('string'),
    basket: DS.belongsTo('App.Basket')
});

App.Basket = DS.Model.extend({
    items: DS.hasMany('App.Item'),
    name: DS.attr('string'),
    username: DS.attr('string'),
})

basket = App.Basket.find(1);
basket.get("items").pushObject(App.Item.find(1));
App.store.commit();

Check out the issues on Github for more details.

Particularly the WIP on relationships with inverse:null and manyToMany.