admin 管理员组文章数量: 1086019
I have the following object relations between my three models (I am not using Backbone-relational... this is just describing the underlying structure of my data) :
Person has many Cars
Car has many Appraisals.
I have a single method to retrieve a Person, which brings along all the Cars and the Appraisals of those Cars. It looks like this:
{id: 1,
name: John Doe,
cars: [
{id: 3, make: 'Porsche',
appraisals: [
{id: 27, amount: '45000', date: '01/01/2011'}
]
},
{id: 4, make: 'Buick', appraisals: []}
]
}
When I create a new Person I pass in this entire mess. In my Person's initialize
function I do this:
...
initialize: function() {
//Cars => Collection of Car
this.cars = new Cars();
_.each(this.get('cars'), function(car) {
this.cars.add(new Car(car));
});
this.unset('cars');
}
...
And in my Car initialize
function I do something similar:
...
initialize: function() {
//Appraisals => Collection of Appraisal
this.appraisals = new Appraisals();
_.each(this.get('appraisals'), function(appraisal) {
this.appraisals.add(new Appraisal(appraisal));
});
this.unset('appraisals');
}
...
I also have to override the toJSON function for Person and Car models.
Is there anything wrong with this? I've seen it suggested elsewhere to make nested collections properties rather than attributes, and my experience confirms that is easier, but I'm wondering if I am breaking some rules or doing something dumb here.
I have the following object relations between my three models (I am not using Backbone-relational... this is just describing the underlying structure of my data) :
Person has many Cars
Car has many Appraisals.
I have a single method to retrieve a Person, which brings along all the Cars and the Appraisals of those Cars. It looks like this:
{id: 1,
name: John Doe,
cars: [
{id: 3, make: 'Porsche',
appraisals: [
{id: 27, amount: '45000', date: '01/01/2011'}
]
},
{id: 4, make: 'Buick', appraisals: []}
]
}
When I create a new Person I pass in this entire mess. In my Person's initialize
function I do this:
...
initialize: function() {
//Cars => Collection of Car
this.cars = new Cars();
_.each(this.get('cars'), function(car) {
this.cars.add(new Car(car));
});
this.unset('cars');
}
...
And in my Car initialize
function I do something similar:
...
initialize: function() {
//Appraisals => Collection of Appraisal
this.appraisals = new Appraisals();
_.each(this.get('appraisals'), function(appraisal) {
this.appraisals.add(new Appraisal(appraisal));
});
this.unset('appraisals');
}
...
I also have to override the toJSON function for Person and Car models.
Is there anything wrong with this? I've seen it suggested elsewhere to make nested collections properties rather than attributes, and my experience confirms that is easier, but I'm wondering if I am breaking some rules or doing something dumb here.
Share Improve this question asked Aug 29, 2011 at 22:25 aw crudaw crud 8,89121 gold badges76 silver badges117 bronze badges 1- Hey, @RenderIn. I notice that your bounty is going to expire in a few hours, and you haven't made any ments or edits lately. Do you still have any questions? – s4y Commented Sep 9, 2011 at 2:57
5 Answers
Reset to default 4I don't have the answer for 'storing nested collections as properties or as attributes' question, but I think you can simplify your code a bit initializing nested collections like this:
Person:
...
initialize: function() {
this.cars = new Cars(this.get('cars'));
this.unset('cars');
}
...
Car:
...
initialize: function() {
this.appraisals = new Appraisals(this.get('appraisals'));
this.unset('appraisals');
}
...
I answered a similar question here: backbone.js - getting extra data along with the request
In the answer that I provided, it was more about a collection owning a model association — a has one, basically.
I think a Person should have a CarsList containing Car models. A Car should have an AppraisalsList containing Appraisal models. You would probably override the parse and toJSON functions of Person and Car as needed.
I would definitely avoid using attributes for associations. The unset functions in the above examples are a bad smell to me.
If I may give my 2 cents worth of input(s):
If you were to draw an OOD class diagram of the classes and model the associations in any object-oriented language of your choice (other than javascript) how would you do it?
You see backbone.js helps put 'structure' to your javascript that could bee an tangled spaghetti code. So if you Person has many Cars and a Car has many Appraisals you have two options: Compositions vs. Associations
Composition: What you are doing above: A person object is responsible for creating the cars and car objects for creating appraisals. The 'lifetime' of each object is dependent on the parent. Now that may/may not be how it 'should' be modeled, but that's the choice you've made.
Now, let's see simple associations. You create the person, cars, and appraisals independently (probably appraisal cannot exist without the car, but let's assume otherwise for now).
Now these objects are created but you need to "wire up" these associations - you can do that externally in a separate "initializer" class/container so to speak and just use setter/getters to connect them.
Conclusion: Use what best models your domain and don't let it be governed by your data store (i.e., the JSON object in this case). Backbone's sheer beauty es from this ability of imparting classic OO structure to your code and thinking in that way when coding. So choose a good mix of OO relations (positions, aggregations or simple associations) and select the 'best model' for your problem and implement accordingly.
Combining with @kulesa's suggestion, you'll "clean up" your code and achieve exactly what you want without worrying about breaking any principles/practices while organizing your code effectively.
Hope this helps!
I don’t personally think it makes sense to use properties to store some of a model’s data. What experiences did you have that made properties feel easier?
Backbone, internally, appears to use properties only for metadata (e.g. the by-id and by-cid maps of the models in a collection) and quick access to attributes (e.g. the id
property, which is updated whenever the id
attribute changes). Using properties also stops you from using Backbone’s event system or .get()
/.set()
, and forces you to override .toJSON()
.
Sticking with attributes, I believe that you could get the same result by overriding .set()
— It gets called when a new instance of a model is created, before .initialize()
, and it will also be called if something else tries to set any attribtues. I once did something similar like this:
var Person = Backbone.Model.extend({
set: function(attributes, options){
var outAttributes = {};
_.each(attributes, function(value, name){
switch(name){
case 'cars':
outAttributes.cars = new Cars(value);
break;
default:
outAttributes[name] = value;
}
}, this);
Backbone.Model.prototype.set.call(this, outAttributes, options);
}
});
…you could modify it to, say, update an existing Cars instance instead of creating a new one.
.set()
is also where Backbone updates the value of the id
property, so if you choose to use properties instead of attributes, it might still be the best to suck in the values (instead of .initialize()
).
I had a similar situation and I solved it this way:
parse: function(data) {
if (data.Success) {
var policies = Rens.get('Policies').model, // model with nested collextion
claims = Rens.get('Claims').model; // model with nested collextion
// reseting collections
claims.claims.reset();
policies.policies.reset();
$(data.Result.Policies).each(function(i, policy) {
var claimsList = policy.ClaimsList,
policyWithClaims = _.clone(policy);
claims.claims.add(claimsList);
_.extend(policyWithClaims, {
ClaimsList: claims.getPolicyClaims.bind({
context: claims,
policyNumber: policy.PolicyNumber
}),
CarYearString: Rens.formatDate(policy.CarYear).date.HH,
PolicyEndDateString: Rens.formatDate(policy.PolicyEndDate).fullDate
});
policies.policies.add(policyWithClaims);
});
}
}
After this i have collection with policies and each policy has attribute with method linked to claims collection.
claims.getPolicyClaims
returns all claims for current policy
本文标签:
版权声明:本文标题:javascript - Is it okay to delete attributes in my Backbone.Model's initialize method, and change them to properties of 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1744097957a2533248.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论