Skip to content
This repository was archived by the owner on Jan 11, 2024. It is now read-only.

Commit 317c99b

Browse files
committed
attributes is now a public property, uncloned. documenting comparator, and more.
1 parent a72920d commit 317c99b

File tree

3 files changed

+86
-39
lines changed

3 files changed

+86
-39
lines changed

Diff for: backbone.js

+14-18
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,10 @@
112112
// Create a new model, with defined attributes.
113113
// If you do not specify the id, a negative id will be assigned for you.
114114
Backbone.Model = function(attributes) {
115-
this._attributes = {};
115+
this.attributes = {};
116116
this.cid = _.uniqueId('c');
117117
this.set(attributes || {}, {silent : true});
118-
this._previousAttributes = this.attributes();
119-
};
120-
121-
// `attributes` is aliased as `toJSON`, for use with `JSON.stringify`.
122-
var toJSON = function() {
123-
return _.clone(this._attributes);
118+
this._previousAttributes = _.clone(this.attributes);
124119
};
125120

126121
// Attach all inheritable methods to the Model prototype.
@@ -134,12 +129,13 @@
134129
_changed : false,
135130

136131
// Return a copy of the model's `attributes` object.
137-
toJSON : toJSON,
138-
attributes : toJSON,
132+
toJSON : function() {
133+
return _.clone(this.attributes);
134+
},
139135

140136
// Get the value of an attribute.
141137
get : function(attr) {
142-
return this._attributes[attr];
138+
return this.attributes[attr];
143139
},
144140

145141
// Set a hash of model attributes on the object, firing `changed` unless you
@@ -149,8 +145,8 @@
149145
// Extract attributes and options.
150146
options || (options = {});
151147
if (!attrs) return this;
152-
attrs = attrs._attributes || attrs;
153-
var now = this._attributes;
148+
attrs = attrs.attributes || attrs;
149+
var now = this.attributes;
154150

155151
// Run validation if `validate` is defined.
156152
if (this.validate) {
@@ -186,8 +182,8 @@
186182
// silence it.
187183
unset : function(attr, options) {
188184
options || (options = {});
189-
var value = this._attributes[attr];
190-
delete this._attributes[attr];
185+
var value = this.attributes[attr];
186+
delete this.attributes[attr];
191187
if (!options.silent) {
192188
this._changed = true;
193189
this.trigger('change:' + attr, this);
@@ -234,7 +230,7 @@
234230

235231
// Create a new model with identical attributes to this one.
236232
clone : function() {
237-
return new (this.constructor)(this.attributes());
233+
return new this.constructor(this);
238234
},
239235

240236
// A model is new if it has never been saved to the server, and has a negative
@@ -247,14 +243,14 @@
247243
// Calling this will cause all objects observing the model to update.
248244
change : function() {
249245
this.trigger('change', this);
250-
this._previousAttributes = this.attributes();
246+
this._previousAttributes = _.clone(this.attributes);
251247
this._changed = false;
252248
},
253249

254250
// Determine if the model has changed since the last `changed` event.
255251
// If you specify an attribute name, determine if that attribute has changed.
256252
hasChanged : function(attr) {
257-
if (attr) return this._previousAttributes[attr] != this._attributes[attr];
253+
if (attr) return this._previousAttributes[attr] != this.attributes[attr];
258254
return this._changed;
259255
},
260256

@@ -263,7 +259,7 @@
263259
// view need to be updated and/or what attributes need to be persisted to
264260
// the server.
265261
changedAttributes : function(now) {
266-
var old = this._previousAttributes, now = now || this.attributes(), changed = false;
262+
var old = this._previousAttributes, now = now || this.attributes, changed = false;
267263
for (var attr in now) {
268264
if (!_.isEqual(old[attr], now[attr])) {
269265
changed = changed || {};

Diff for: index.html

+72-16
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
<li><a href="#Model-id">id</a></li>
154154
<li><a href="#Model-cid">cid</a></li>
155155
<li><a href="#Model-attributes">attributes</a></li>
156+
<li>- <a href="#Model-toJSON">toJSON</a></li>
156157
<li><a href="#Model-save">save</a></li>
157158
<li><a href="#Model-destroy">destroy</a></li>
158159
<li><a href="#Model-validate">validate</a></li>
@@ -171,12 +172,14 @@
171172
</a>
172173
<ul class="toc_section">
173174
<li><a href="#Collection-extend">extend</a></li>
175+
<li><a href="#Collection-models">models</a></li>
174176
<li><a href="#Collection-Underscore-Methods"><b>Underscore Methods (24)</b></a></li>
175177
<li><a href="#Collection-add">add</a></li>
176178
<li><a href="#Collection-remove">remove</a></li>
177179
<li><a href="#Collection-get">get</a></li>
178180
<li><a href="#Collection-getByCid">getByCid</a></li>
179181
<li><a href="#Collection-at">at</a></li>
182+
<li><a href="#Collection-comparator">comparator</a></li>
180183
<li><a href="#Collection-sort">sort</a></li>
181184
<li><a href="#Collection-pluck">pluck</a></li>
182185
<li><a href="#Model-url">url</a></li>
@@ -201,6 +204,9 @@
201204
<li><a href="#View-make">make</a></li>
202205
<li><a href="#View-handleEvents">handleEvents</a></li>
203206
</ul>
207+
<a class="toc_title" href="#changelog">
208+
Change Log
209+
</a>
204210
</div>
205211

206212
<div class="container">
@@ -492,10 +498,20 @@ <h2 id="Model">Backbone.Model</h2>
492498
</p>
493499

494500
<p id="Model-attributes">
495-
<b class="header">attributes</b><code>model.attributes()</code>
501+
<b class="header">attributes</b><code>model.attributes</code>
502+
<br />
503+
The <b>attributes</b> property is the internal hash containing the model's
504+
state. Please use <tt>set</tt> to update the attributes instead of modifying
505+
them directly. If you'd like to retrieve and munge a copy of the model's
506+
attributes, use <tt>toJSON</tt> instead.
507+
</p>
508+
509+
<p id="Model-toJSON">
510+
<b class="header">toJSON</b><code>model.toJSON</code>
496511
<br />
497-
Return a copy of the model's <b>attributes</b>. This can be used for persistence,
498-
serialization, or for augmentation before being handed off to a view.
512+
Return a copy of the model's <b>attributes</b> for JSON stringification.
513+
This can be used for persistence, serialization, or for augmentation before
514+
being handed off to a view.
499515
</p>
500516

501517
<pre class="runnable">
@@ -506,7 +522,7 @@ <h2 id="Model">Backbone.Model</h2>
506522

507523
artist.set({birthday: "December 16, 1866"});
508524

509-
alert(JSON.stringify(artist.attributes()));
525+
alert(JSON.stringify(artist));
510526
</pre>
511527

512528
<p id="Model-save">
@@ -519,6 +535,11 @@ <h2 id="Model">Backbone.Model</h2>
519535
exists on the server, the save will be a <tt>PUT</tt>. Accepts
520536
<tt>success</tt> and <tt>error</tt> callbacks in the options hash.
521537
</p>
538+
539+
<p>
540+
In the following example, notice how because the model has never been
541+
saved previously, <tt>Backbone.sync</tt> receives a <tt>"create"</tt> request.
542+
</p>
522543

523544
<pre class="runnable">
524545
Backbone.sync = function(method, model) {
@@ -542,11 +563,9 @@ <h2 id="Model">Backbone.Model</h2>
542563
</p>
543564

544565
<pre>
545-
book.destroy({
546-
success: function(model, response) {
547-
...
548-
}
549-
});
566+
book.destroy({success: function(model, response) {
567+
...
568+
}});
550569
</pre>
551570

552571
<p id="Model-validate">
@@ -699,6 +718,15 @@ <h2 id="Collection">Backbone.Collection</h2>
699718
providing instance <b>properties</b>, as well as optional properties to be attached
700719
directly to the collection constructor function.
701720
</p>
721+
722+
<p id="Collection-models">
723+
<b class="header">models</b><code>collection.models</code>
724+
<br />
725+
Raw access to the JavaScript array of models inside of the collection. Usually you'll
726+
want to use <tt>get</tt>, <tt>at</tt>, or the <b>Underscore methods</b>
727+
to access model objects, but occasionally a direct reference to the array
728+
is desired.
729+
</p>
702730

703731
<p id="Collection-Underscore-Methods">
704732
<b class="header">Underscore Methods (24)</b>
@@ -761,14 +789,13 @@ <h2 id="Collection">Backbone.Collection</h2>
761789
</p>
762790

763791
<pre class="runnable">
792+
var Ship = Backbone.Model;
764793
var ships = new Backbone.Collection();
765794

766795
ships.bind("add", function(ship) {
767796
alert("Ahoy " + ship.get("name") + "!");
768797
});
769798

770-
var Ship = Backbone.Model.extend({});
771-
772799
ships.add([
773800
new Ship({name: "Flying Dutchman"}),
774801
new Ship({name: "Black Pearl"})
@@ -805,6 +832,37 @@ <h2 id="Collection">Backbone.Collection</h2>
805832
is sorted, and if your collection isn't sorted, <b>at</b> will still
806833
retrieve models in insertion order.
807834
</p>
835+
836+
<p id="Collection-comparator">
837+
<b class="header">comparator</b><code>collection.comparator</code>
838+
<br />
839+
By default there is no <b>comparator</b> function on a collection.
840+
If you define a comparator function, it will be used to always maintain
841+
the collection in sorted order. This means that as models are added,
842+
they are inserted at the correct index in <tt>collection.models</tt>.
843+
Comparator functions take a model and return a numeric or string value
844+
by which the model should be ordered relative to others.
845+
</p>
846+
847+
<p>
848+
Note how all of the chapters in this example come out in the
849+
proper order:
850+
</p>
851+
852+
<pre class="runnable">
853+
var Chapter = Backbone.Model;
854+
var chapters = new Backbone.Collection();
855+
856+
chapters.comparator = function(chapter) {
857+
return chapter.get("page");
858+
};
859+
860+
chapters.add(new Chapter({page: 9, title: "The End"}));
861+
chapters.add(new Chapter({page: 5, title: "The Middle"}));
862+
chapters.add(new Chapter({page: 1, title: "The Beginning"}));
863+
864+
alert(chapters.pluck('title'));
865+
</pre>
808866

809867
<p id="Collection-sort">
810868
<b class="header">sort</b><code>collection.sort([options])</code>
@@ -991,8 +1049,7 @@ <h2 id="View">Backbone.View</h2>
9911049
<pre>
9921050
ui.Chapter = Backbone.View.extend({
9931051
render: function() {
994-
var data = this.model.attributes();
995-
$(this.el).html(this.template.render(data));
1052+
$(this.el).html(this.template.render(this.model.toJSON()));
9961053
return this;
9971054
}
9981055
});
@@ -1043,8 +1100,7 @@ <h2 id="View">Backbone.View</h2>
10431100
},
10441101

10451102
render: {
1046-
var data = this.document.attributes();
1047-
this.el.html(this.template.render(data));
1103+
$(this.el).html(this.template.render(this.model.toJSON()));
10481104
this.handleEvents();
10491105
return this;
10501106
}
@@ -1057,7 +1113,7 @@ <h2 id="View">Backbone.View</h2>
10571113

10581114

10591115

1060-
<h2 id="changes">Change Log</h2>
1116+
<h2 id="changelog">Change Log</h2>
10611117

10621118
<p>
10631119
<b class="header">0.1.0</b><br />

Diff for: test/model.js

-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ $(document).ready(function() {
2626
var collection = new klass();
2727
collection.add(doc);
2828

29-
test("model: attributes", function() {
30-
ok(doc.attributes() !== attrs, "Attributes are different objects.");
31-
ok(_.isEqual(doc.attributes(), attrs), "but with identical contents.");
32-
});
33-
3429
test("model: url", function() {
3530
equals(doc.url(), '/collection/1-the-tempest');
3631
});

0 commit comments

Comments
 (0)