Reputation: 23
I have two models that relate to each other like this:
hasMany
"Cities";belongsTo
a "Country".I can't figure out how to make these association in an action
of my route.
Here my application
template:
<script type="text/x-handlebars">
<p><button {{action 'save'}}>add data</button></p>
<ul>
{{#each country in model}}
<li>{{country.name}}
<ul>
{{#each city in country.cities}}
<li>{{city.name}}</li>
{{/each}}
</ul>
</li>
{{/each}}
<ul>
</script>
my models are:
App.Countries = DS.Model.extend({
name: DS.attr('string'),
cities: DS.hasMany('cities', {async: true})
});
App.Cities = DS.Model.extend({
name: DS.attr('string'),
country: DS.belongsTo('countries', {async: true})
});
and here the application route:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return this.store.find('countries');
},
actions: {
save: function() {
var store = this.store;
var country = store.createRecord('countries', {
'name': 'France'
});
var city1 = store.createRecord('cities', {
'name': 'Paris'
});
var city2 = store.createRecord('cities', {
'name': 'Marseille'
});
country.get('cities').then(function(cities) {
return cities.pushObject(city1);
});
country.get('cities').then(function(cities) {
return cities.pushObject(city2);
});
city1.set('country', country);
city2.set('country', country);
country.save();
city1.save();
city2.save();
}
}
});
After the action "save" executes, I see in my ember inspector that the records are created, but seems like the associations don't work since the application template doesn't diplay them as I expect.
What's the right way to set association, then?
For reasons that are still voodoo to me, even with the new implementation of DS.JSONSerializer.serializeHasMany
, this strategy for saving records works
country.get('cities').then(function(cities){
return cities.pushObjects([city1,city2]);
});
city1.set('country', country);
city2.set('country', country);
country.save();
city1.save();
city2.save();
but this doesn't:
country.get('cities').pushObjects([city1,city2]);
city1.set('country', country);
city2.set('country', country);
country.save();
city1.save();
city2.save();
Turns out it's the very same problem as in the question Saving a model breaks one to many relationships. The alternative implementation of DS.JSONSerializer.serializeHasMany
fixes it.
@steve-h answers below, suggesting to not treat the cities
property of the country
record as a promise. This fails to work in a slightly different way:
country.get('cities').pushObjects([city1,city2]);
city1.set('country', country);
city2.set('country', country);
country.save();
city1.save();
city2.save();
seems like country
never has links to the two cities
: the <ul>
in the application
template doesn't visualize any city
under the newly created country
.
Inspecting further my original attempt, i.e.
country.get('cities').then(function(cities) {
return cities.pushObject(city1);
});
country.get('cities').then(function(cities) {
return cities.pushObject(city2);
});
city1.set('country', country);
city2.set('country', country);
country.save();
city1.save();
city2.save();
with a breakpoint somewhere in the above snippet, I get the following stacktrace
App.ApplicationRoute.Ember.Route.extend.actions.save (app.js:48)
triggerEvent (ember.js:39606)
trigger (ember.js:42157)
Router.trigger (ember.js:41013)
EmberObject.extend.send (ember.js:39196)
Mixin.create.send (ember.js:15451)
runRegisteredAction (ember.js:34649)
-----> YAY !! at this point the associations are in place,
and correctly displayed in the application template
Backburner.run (ember.js:8160)
apply (ember.js:7992)
run (ember.js:6626)
handleRegisteredAction (ember.js:34647)
(anonymous function) (ember.js:22841)
x.event.dispatch (jquery.js:5095)
v.handle (jquery.js:4766)
-----> here the cities seems to disappear from the country record,
and thus from the <ul> in the application template
The overall effect is that the cities appear in my <ul>
for a fraction of a second and then disappear.
Here a jsbin with the live code.
Upvotes: 0
Views: 152
Reputation: 6947
Your resolution of the promises is where I think you're getting hung up. The save is happening before the promises resolve (where you pushObject
the city) . I haven't tried this, but I think you'll need to do something like this:
save: function() {
var store = this.store;
var country = store.createRecord('countries', {
'name': 'France'
});
var city1 = store.createRecord('cities', {
'name': 'Paris'
});
var city2 = store.createRecord('cities', {
'name': 'Marseille'
});
country.get('cities').pushObjects([city1,city2]);
city1.save();
city2.save();
country.save();
}
Upvotes: 1