Given two models, how can I ensure that an update to the "child" object marks the "parent" object as "dirty" so that calling save
on the parent object does not skip?
Details
Using ember-model, I have defined Person
and Address
models like so:
App.Person = Ember.Model.extend({
id: Ember.attr(),
name: Ember.attr('string'),
address: Ember.belongsTo('App.Address', { key: 'address', embedded: true }),
});
App.Address = Ember.Model.extend({
id: Ember.attr(),
line1: Ember.attr('string'),
line2: Ember.attr('string')
});
Now I have rendered this in a form, and made these attributes editable:
{{input value=model.name classNames="name"}}
{{input value=model.address.line1 classNames="address-line1"}}
{{input value=model.address.line2 classNames="address-line2"}}
<button type='button' {{action 'save'}}>Save</button>
<button type='button' {{action 'cancel'}}>Cancel</button>
So far so good. The last piece of the puzzle is persisting the model to server
actions: {
save: function() {
var model = this.get('model');
var address = model.get('address');
console.log(
"model.get('isDirty')=", model.get('isDirty'), //false
"address.get('isDirty')=", address.get('isDirty') //true
);
model.save();
model.get('address').save();
},
cancel: function() {
var model = this.get('model');
var address = model.get('address');
console.log(
"model.get('isDirty')=", model.get('isDirty'), //false
"address.get('isDirty')=", address.get('isDirty') //true
);
address.revert();
model.revert();
}
}
Here we see that when the user edits the address (either line1
or line2
),
the model
is not considered to be "dirty", and thus ember-model
does not make the adapter call to save()
.
This happens, even though address
is considered to be dirty, and has a relationship defined with model
.
This means that I need to call save
(or revert
) separately on the two objects. I would thus lose atomicity of the operation, and also need to define a new endpoint for the address
objects. I do not want to do either of these.
How can I ensure that updating address
will make model
becomes dirty as well?
Update:
Instead of calling save
on both the "child" and "parent" objects, I found a better way by looking through the source for ember-model:
console.log(
"model.get('isDirty')=", model.get('isDirty'), //false
"address.get('isDirty')=", address.get('isDirty') //true
);
// model.get('address').save();
if (address.get('isDirty')) {
model._relationshipBecameDirty('address');
}
console.log(
"model.get('isDirty')=", model.get('isDirty'), //true
"address.get('isDirty')=", address.get('isDirty') //true
);
model.save();
This ensures atomicity is preserved, however calling a private method directly like this does not seem right. Is there a better way?
Currently the only usages of this method - _relationshipBecameDirty
- are in has_many_array.js
in ember-model, and I was not able to find any instance in belongs_to.js
. If this is intentional by design in meber-model, what is the proper way to accomplish this?