Reputation: 7148
I have a model with several observers, and after watching Stefan Penner's talk on removing observers, I'd like to do the same with mine:
import DS from "ember-data";
import Ember from "ember";
import TimeableMixin from "../mixins/timeable";
export default DS.Model.extend(TimeableMixin, {
employer: DS.belongsTo("company", {async: true}),
updateDescription: function() {
let description = "";
const hasOccupation = !Ember.isBlank(this.get("occupation")),
hasEmployer = !Ember.isBlank(this.get("employer.name"));
if (hasOccupation) {
description += this.get("occupation");
}
else {
if (this.get("type")) {
description += `${Ember.String.capitalize(this.get("type"))} Job`;
}
else {
description = "Full-time Job"; // we have to hard-code the default, because of async behaviour
}
}
if (hasEmployer) {
description += ` at ${this.get("employer.name")}`;
}
this.get("income").then((resolvedIncome) => {
resolvedIncome.set("description", description);
});
}.observes("employer.name", "occupation", "type"),
occupation: DS.attr("string"),
income: DS.belongsTo("income", {async: true}), /* Annual income ($) */
incomeChanged: function() {
if (this.get("isHourly")) {
let hourlyRate = parseInt(this.get("hourlyRate")), weeklyHours = parseInt(this.get("weeklyHours"));
if (hourlyRate && weeklyHours) {
let yearlySalary = (hourlyRate * weeklyHours) * 52.1775; // there are 52.1775 weeks in a year
this.get("income").then((resolvedIncome) => {
resolvedIncome.set("value", yearlySalary);
});
}
}
}.observes("hourlyRate", "weeklyHours"),
// ...
});
I have considered something akin to "actions down, data up", where the controller or component might handle such a computed property:
export default Ember.Component.extend({
updatedDescription: Ember.computed("employment.employer.name", "employment.occupation", "employment.type", function() {
let description = "";
const hasOccupation = !Ember.isBlank(this.get("occupation")),
hasEmployer = !Ember.isBlank(this.get("employer.name"));
if (hasOccupation) {
description += this.get("occupation");
}
else {
if (this.get("type")) {
description += `${Ember.String.capitalize(this.get("type"))} Job`;
}
else {
description = "Full-time Job"; // we have to hard-code the default, because of async behaviour
}
}
if (hasEmployer) {
description += ` at ${this.get("employer.name")}`;
}
return description;
}),
employment: null,
// ...
});
But this would prevent setting the description
property on my model, which is initially what I set out to do.
How can I refactor my model observers to use computed properties, and remove them?
Upvotes: 0
Views: 134
Reputation: 2409
Instead of setting the description property, set the description property as computed and update it when necessary:
description: Ember.computed("employer.name", "occupation", "type", function() {
let description = "";
const hasOccupation = !Ember.isBlank(this.get("occupation")),
hasEmployer = !Ember.isBlank(this.get("employer.name"));
if (hasOccupation) {
description += this.get("occupation");
}
else {
if (this.get("type")) {
description += `${Ember.String.capitalize(this.get("type"))} Job`;
}
else {
description = "Full-time Job";
}
}
if (hasEmployer) {
description += ` at ${this.get("employer.name")}`;
}
return description;
}
I generally try to avoid async operations within models because it can get pretty messy when you're waiting on a lot of stuff to load.
Upvotes: 0