spine-rails 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -4,6 +4,6 @@ source 'http://rubygems.org'
4
4
  gemspec
5
5
  # Rails is already being pulled in through gemspec
6
6
  # gem "rails", :git => "git://github.com/rails/rails.git"
7
- gem "rack", :git => "git://github.com/rack/rack.git"
8
- gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
9
- gem "i18n", "0.6.0beta1"
7
+ gem "rack"
8
+ gem "sprockets"
9
+ gem "i18n"
data/README.md CHANGED
@@ -9,7 +9,7 @@ This gem requires the use of [Rails 3.1](http://rubyonrails.org), [CoffeeScript]
9
9
  This gem does two things:
10
10
 
11
11
  * Adds Spine to the asset pipeline, so you can easily require it in your applications: `//= require spine`
12
-
12
+
13
13
  * Adds some Spine generators, so you can easily create Spine Models, Views and Controllers.
14
14
 
15
15
  ### Installation
@@ -17,26 +17,26 @@ This gem does two things:
17
17
  In your Gemfile, add this line:
18
18
 
19
19
  gem "spine-rails"
20
-
20
+
21
21
  Then run the following commands:
22
22
 
23
23
  bundle install
24
-
24
+
25
25
  rails generate spine:new
26
26
 
27
27
  ### Layout and namespacing
28
28
 
29
29
  Running `rails g spine:new` will create the following directory structure:
30
-
30
+
31
31
  app/assets/javascripts/app/models/
32
32
  app/assets/javascripts/app/views/
33
33
  app/assets/javascripts/app/controllers/
34
34
  app/assets/javascripts/app/index.js.coffee
35
-
35
+
36
36
  By default your application will be namespaced by the `app` directory. You can specify a different namespace with the `--app` option:
37
37
 
38
38
  rails g spine:new --app foo_bar
39
-
39
+
40
40
  **NOTE:** If you use the `--app` option here, then you will also have to specify it with other generators.
41
41
 
42
42
  Use the top-level level `index.js.coffee` file to setup namespacing and initial controller instantiation.
@@ -48,19 +48,19 @@ spine-rails provides three simple generators to help you get started:
48
48
  ### Model
49
49
 
50
50
  rails g spine:model User email username full_name
51
-
51
+
52
52
  This generator creates a very minimal model inside `app/assets/javascript/app/models`. You have to provide a list of attributes for the model.
53
53
 
54
54
  ### Controller
55
-
55
+
56
56
  rails g spine:controller Users
57
-
58
- This generator creates a minimal `Users` controller in `app/assets/javascripts/app/controllers` to get you started.
57
+
58
+ This generator creates a minimal `Users` controller in `app/assets/javascripts/app/controllers` to get you started.
59
59
 
60
60
  ### View
61
61
 
62
62
  rails g spine:view users/index
63
-
63
+
64
64
  This generator creates a blank Spine view `app/assets/javascripts/app/views/users/index.jst.ejs`.
65
65
 
66
66
  The generator will create views in `hamljs`, `eco` or `ejs` format, depending on the gems availale:
@@ -82,13 +82,13 @@ Edit your Gemfile and add
82
82
  Install the gem and generate resource.
83
83
 
84
84
  bundle install
85
-
85
+
86
86
  rails g scaffold Post title:string content:string
87
87
  rake db:migrate
88
-
88
+
89
89
  rails g spine:new
90
90
  rails g spine:model Post title content
91
- rails g spine:controllers Posts
91
+ rails g spine:controller Posts
92
92
 
93
93
  You now have the default Spine data structures available to work with.
94
94
 
@@ -98,22 +98,22 @@ Now you can use Spine:
98
98
 
99
99
  // Sends an AJAX POST to the server
100
100
  var post = App.Post.create({
101
- title: 'Hello World!',
101
+ title: 'Hello World!',
102
102
  content: 'Spine & Rails, sitting in a tree!'
103
- });
103
+ });
104
104
 
105
105
  // => ID returned from Rails
106
- post.id;
107
-
106
+ post.id;
107
+
108
108
  // Sends AJAX PUT to the server
109
109
  post.updateAttributes({title: 'Goodbye'});
110
-
110
+
111
111
  Reload the page, then:
112
112
 
113
113
  App.Post.fetch(); // Fetch all posts
114
-
114
+
115
115
  App.Post.first().content;
116
-
116
+
117
117
  For more information on how to integrate Spine with Rails, please see the [Rails guide](http://spinejs.com/docs/rails).
118
118
 
119
119
  Also if you want to have some useful helpers to bridge the gap between Spine and Rails, then [spine-extensions](https://github.com/dnagir/spine-extensions) is for you.
@@ -1,18 +1,11 @@
1
1
  (function() {
2
- var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, isBlank, makeArray, moduleKeywords;
3
- var __slice = Array.prototype.slice, __indexOf = Array.prototype.indexOf || function(item) {
4
- for (var i = 0, l = this.length; i < l; i++) {
5
- if (this[i] === item) return i;
6
- }
7
- return -1;
8
- }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
9
- for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
10
- function ctor() { this.constructor = child; }
11
- ctor.prototype = parent.prototype;
12
- child.prototype = new ctor;
13
- child.__super__ = parent.prototype;
14
- return child;
15
- };
2
+ var $, Controller, Events, Log, Model, Module, Spine, isArray, isBlank, makeArray, moduleKeywords,
3
+ __slice = Array.prototype.slice,
4
+ __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
5
+ __hasProp = Object.prototype.hasOwnProperty,
6
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
7
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
8
+
16
9
  Events = {
17
10
  bind: function(ev, callback) {
18
11
  var calls, evs, name, _i, _len;
@@ -36,14 +29,10 @@
36
29
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
37
30
  ev = args.shift();
38
31
  list = this.hasOwnProperty('_callbacks') && ((_ref = this._callbacks) != null ? _ref[ev] : void 0);
39
- if (!list) {
40
- return false;
41
- }
32
+ if (!list) return;
42
33
  for (_i = 0, _len = list.length; _i < _len; _i++) {
43
34
  callback = list[_i];
44
- if (callback.apply(this, args) === false) {
45
- break;
46
- }
35
+ if (callback.apply(this, args) === false) break;
47
36
  }
48
37
  return true;
49
38
  },
@@ -54,126 +43,130 @@
54
43
  return this;
55
44
  }
56
45
  list = (_ref = this._callbacks) != null ? _ref[ev] : void 0;
57
- if (!list) {
58
- return this;
59
- }
46
+ if (!list) return this;
60
47
  if (!callback) {
61
48
  delete this._callbacks[ev];
62
49
  return this;
63
50
  }
64
51
  for (i = 0, _len = list.length; i < _len; i++) {
65
52
  cb = list[i];
66
- if (cb === callback) {
67
- list = list.slice();
68
- list.splice(i, 1);
69
- this._callbacks[ev] = list;
70
- break;
71
- }
53
+ if (!(cb === callback)) continue;
54
+ list = list.slice();
55
+ list.splice(i, 1);
56
+ this._callbacks[ev] = list;
57
+ break;
72
58
  }
73
59
  return this;
74
60
  }
75
61
  };
62
+
76
63
  Log = {
77
64
  trace: true,
78
65
  logPrefix: '(App)',
79
66
  log: function() {
80
67
  var args;
81
68
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
82
- if (!this.trace) {
83
- return;
84
- }
85
- if (typeof console === 'undefined') {
86
- return;
69
+ if (!this.trace) return;
70
+ if (this.logPrefix) args.unshift(this.logPrefix);
71
+ if (typeof console !== "undefined" && console !== null) {
72
+ if (typeof console.log === "function") console.log.apply(console, args);
87
73
  }
88
- if (this.logPrefix) {
89
- args.unshift(this.logPrefix);
90
- }
91
- console.log.apply(console, args);
92
74
  return this;
93
75
  }
94
76
  };
77
+
95
78
  moduleKeywords = ['included', 'extended'];
79
+
96
80
  Module = (function() {
81
+
97
82
  Module.include = function(obj) {
98
- var included, key, value;
99
- if (!obj) {
100
- throw 'include(obj) requires obj';
101
- }
83
+ var key, value, _ref;
84
+ if (!obj) throw 'include(obj) requires obj';
102
85
  for (key in obj) {
103
86
  value = obj[key];
104
- if (__indexOf.call(moduleKeywords, key) < 0) {
105
- this.prototype[key] = value;
106
- }
107
- }
108
- included = obj.included;
109
- if (included) {
110
- included.apply(this);
87
+ if (__indexOf.call(moduleKeywords, key) < 0) this.prototype[key] = value;
111
88
  }
89
+ if ((_ref = obj.included) != null) _ref.apply(this);
112
90
  return this;
113
91
  };
92
+
114
93
  Module.extend = function(obj) {
115
- var extended, key, value;
116
- if (!obj) {
117
- throw 'extend(obj) requires obj';
118
- }
94
+ var key, value, _ref;
95
+ if (!obj) throw 'extend(obj) requires obj';
119
96
  for (key in obj) {
120
97
  value = obj[key];
121
- if (__indexOf.call(moduleKeywords, key) < 0) {
122
- this[key] = value;
123
- }
124
- }
125
- extended = obj.extended;
126
- if (extended) {
127
- extended.apply(this);
98
+ if (__indexOf.call(moduleKeywords, key) < 0) this[key] = value;
128
99
  }
100
+ if ((_ref = obj.extended) != null) _ref.apply(this);
129
101
  return this;
130
102
  };
103
+
131
104
  Module.proxy = function(func) {
132
- return __bind(function() {
133
- return func.apply(this, arguments);
134
- }, this);
105
+ var _this = this;
106
+ return function() {
107
+ return func.apply(_this, arguments);
108
+ };
135
109
  };
110
+
136
111
  Module.prototype.proxy = function(func) {
137
- return __bind(function() {
138
- return func.apply(this, arguments);
139
- }, this);
112
+ var _this = this;
113
+ return function() {
114
+ return func.apply(_this, arguments);
115
+ };
140
116
  };
117
+
141
118
  function Module() {
142
- if (typeof this.init === "function") {
143
- this.init.apply(this, arguments);
144
- }
119
+ if (typeof this.init === "function") this.init.apply(this, arguments);
145
120
  }
121
+
146
122
  return Module;
123
+
147
124
  })();
148
- Model = (function() {
149
- __extends(Model, Module);
125
+
126
+ Model = (function(_super) {
127
+
128
+ __extends(Model, _super);
129
+
150
130
  Model.extend(Events);
131
+
151
132
  Model.records = {};
133
+
134
+ Model.crecords = {};
135
+
152
136
  Model.attributes = [];
137
+
153
138
  Model.configure = function() {
154
139
  var attributes, name;
155
140
  name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
156
141
  this.className = name;
157
142
  this.records = {};
158
- if (attributes.length) {
159
- this.attributes = attributes;
160
- }
143
+ this.crecords = {};
144
+ if (attributes.length) this.attributes = attributes;
161
145
  this.attributes && (this.attributes = makeArray(this.attributes));
162
146
  this.attributes || (this.attributes = []);
163
147
  this.unbind();
164
148
  return this;
165
149
  };
150
+
166
151
  Model.toString = function() {
167
152
  return "" + this.className + "(" + (this.attributes.join(", ")) + ")";
168
153
  };
154
+
169
155
  Model.find = function(id) {
170
156
  var record;
171
157
  record = this.records[id];
172
- if (!record) {
173
- throw 'Unknown record';
174
- }
158
+ if (!record && ("" + id).match(/c-\d+/)) return this.findCID(id);
159
+ if (!record) throw 'Unknown record';
175
160
  return record.clone();
176
161
  };
162
+
163
+ Model.findCID = function(cid) {
164
+ var record;
165
+ record = this.crecords[cid];
166
+ if (!record) throw 'Unknown record';
167
+ return record.clone();
168
+ };
169
+
177
170
  Model.exists = function(id) {
178
171
  try {
179
172
  return this.find(id);
@@ -181,27 +174,26 @@
181
174
  return false;
182
175
  }
183
176
  };
177
+
184
178
  Model.refresh = function(values, options) {
185
179
  var record, records, _i, _len;
186
- if (options == null) {
187
- options = {};
188
- }
180
+ if (options == null) options = {};
189
181
  if (options.clear) {
190
182
  this.records = {};
183
+ this.crecords = {};
191
184
  }
192
185
  records = this.fromJSON(values);
193
- if (!isArray(records)) {
194
- records = [records];
195
- }
186
+ if (!isArray(records)) records = [records];
196
187
  for (_i = 0, _len = records.length; _i < _len; _i++) {
197
188
  record = records[_i];
198
- record.newRecord = false;
199
- record.id || (record.id = guid());
189
+ record.id || (record.id = record.cid);
200
190
  this.records[record.id] = record;
191
+ this.crecords[record.cid] = record;
201
192
  }
202
- this.trigger('refresh', !options.clear && records);
193
+ this.trigger('refresh', !options.clear && this.cloneArray(records));
203
194
  return this;
204
195
  };
196
+
205
197
  Model.select = function(callback) {
206
198
  var id, record, result;
207
199
  result = (function() {
@@ -210,30 +202,29 @@
210
202
  _results = [];
211
203
  for (id in _ref) {
212
204
  record = _ref[id];
213
- if (callback(record)) {
214
- _results.push(record);
215
- }
205
+ if (callback(record)) _results.push(record);
216
206
  }
217
207
  return _results;
218
208
  }).call(this);
219
209
  return this.cloneArray(result);
220
210
  };
211
+
221
212
  Model.findByAttribute = function(name, value) {
222
213
  var id, record, _ref;
223
214
  _ref = this.records;
224
215
  for (id in _ref) {
225
216
  record = _ref[id];
226
- if (record[name] === value) {
227
- return record.clone();
228
- }
217
+ if (record[name] === value) return record.clone();
229
218
  }
230
219
  return null;
231
220
  };
221
+
232
222
  Model.findAllByAttribute = function(name, value) {
233
223
  return this.select(function(item) {
234
224
  return item[name] === value;
235
225
  });
236
226
  };
227
+
237
228
  Model.each = function(callback) {
238
229
  var key, value, _ref, _results;
239
230
  _ref = this.records;
@@ -244,23 +235,28 @@
244
235
  }
245
236
  return _results;
246
237
  };
238
+
247
239
  Model.all = function() {
248
240
  return this.cloneArray(this.recordsValues());
249
241
  };
242
+
250
243
  Model.first = function() {
251
244
  var record;
252
245
  record = this.recordsValues()[0];
253
246
  return record != null ? record.clone() : void 0;
254
247
  };
248
+
255
249
  Model.last = function() {
256
250
  var record, values;
257
251
  values = this.recordsValues();
258
252
  record = values[values.length - 1];
259
253
  return record != null ? record.clone() : void 0;
260
254
  };
255
+
261
256
  Model.count = function() {
262
257
  return this.recordsValues().length;
263
258
  };
259
+
264
260
  Model.deleteAll = function() {
265
261
  var key, value, _ref, _results;
266
262
  _ref = this.records;
@@ -271,6 +267,7 @@
271
267
  }
272
268
  return _results;
273
269
  };
270
+
274
271
  Model.destroyAll = function() {
275
272
  var key, value, _ref, _results;
276
273
  _ref = this.records;
@@ -281,17 +278,21 @@
281
278
  }
282
279
  return _results;
283
280
  };
284
- Model.update = function(id, atts) {
285
- return this.find(id).updateAttributes(atts);
281
+
282
+ Model.update = function(id, atts, options) {
283
+ return this.find(id).updateAttributes(atts, options);
286
284
  };
287
- Model.create = function(atts) {
285
+
286
+ Model.create = function(atts, options) {
288
287
  var record;
289
288
  record = new this(atts);
290
- return record.save();
289
+ return record.save(options);
291
290
  };
292
- Model.destroy = function(id) {
293
- return this.find(id).destroy();
291
+
292
+ Model.destroy = function(id, options) {
293
+ return this.find(id).destroy(options);
294
294
  };
295
+
295
296
  Model.change = function(callbackOrParams) {
296
297
  if (typeof callbackOrParams === 'function') {
297
298
  return this.bind('change', callbackOrParams);
@@ -299,6 +300,7 @@
299
300
  return this.trigger('change', callbackOrParams);
300
301
  }
301
302
  };
303
+
302
304
  Model.fetch = function(callbackOrParams) {
303
305
  if (typeof callbackOrParams === 'function') {
304
306
  return this.bind('fetch', callbackOrParams);
@@ -306,17 +308,15 @@
306
308
  return this.trigger('fetch', callbackOrParams);
307
309
  }
308
310
  };
311
+
309
312
  Model.toJSON = function() {
310
313
  return this.recordsValues();
311
314
  };
315
+
312
316
  Model.fromJSON = function(objects) {
313
317
  var value, _i, _len, _results;
314
- if (!objects) {
315
- return;
316
- }
317
- if (typeof objects === 'string') {
318
- objects = JSON.parse(objects);
319
- }
318
+ if (!objects) return;
319
+ if (typeof objects === 'string') objects = JSON.parse(objects);
320
320
  if (isArray(objects)) {
321
321
  _results = [];
322
322
  for (_i = 0, _len = objects.length; _i < _len; _i++) {
@@ -328,10 +328,12 @@
328
328
  return new this(objects);
329
329
  }
330
330
  };
331
+
331
332
  Model.fromForm = function() {
332
333
  var _ref;
333
334
  return (_ref = new this).fromForm.apply(_ref, arguments);
334
335
  };
336
+
335
337
  Model.recordsValues = function() {
336
338
  var key, result, value, _ref;
337
339
  result = [];
@@ -342,6 +344,7 @@
342
344
  }
343
345
  return result;
344
346
  };
347
+
345
348
  Model.cloneArray = function(array) {
346
349
  var value, _i, _len, _results;
347
350
  _results = [];
@@ -351,21 +354,29 @@
351
354
  }
352
355
  return _results;
353
356
  };
354
- Model.prototype.newRecord = true;
357
+
358
+ Model.idCounter = 0;
359
+
360
+ Model.uid = function() {
361
+ return this.idCounter++;
362
+ };
363
+
355
364
  function Model(atts) {
356
365
  Model.__super__.constructor.apply(this, arguments);
357
- this.ids = [];
358
- if (atts) {
359
- this.load(atts);
360
- }
366
+ if (atts) this.load(atts);
367
+ this.cid || (this.cid = 'c-' + this.constructor.uid());
361
368
  }
369
+
362
370
  Model.prototype.isNew = function() {
363
- return this.newRecord;
371
+ return !this.exists();
364
372
  };
373
+
365
374
  Model.prototype.isValid = function() {
366
375
  return !this.validate();
367
376
  };
377
+
368
378
  Model.prototype.validate = function() {};
379
+
369
380
  Model.prototype.load = function(atts) {
370
381
  var key, value;
371
382
  for (key in atts) {
@@ -378,6 +389,7 @@
378
389
  }
379
390
  return this;
380
391
  };
392
+
381
393
  Model.prototype.attributes = function() {
382
394
  var key, result, _i, _len, _ref;
383
395
  result = {};
@@ -392,81 +404,92 @@
392
404
  }
393
405
  }
394
406
  }
395
- if (this.id) {
396
- result.id = this.id;
397
- }
407
+ if (this.id) result.id = this.id;
398
408
  return result;
399
409
  };
410
+
400
411
  Model.prototype.eql = function(rec) {
401
- var _ref, _ref2;
402
- return rec && rec.constructor === this.constructor && (rec.id === this.id || (_ref = this.id, __indexOf.call(rec.ids, _ref) >= 0) || (_ref2 = rec.id, __indexOf.call(this.ids, _ref2) >= 0));
412
+ return !!(rec && rec.constructor === this.constructor && (rec.id === this.id || rec.cid === this.cid));
403
413
  };
404
- Model.prototype.save = function() {
414
+
415
+ Model.prototype.save = function(options) {
405
416
  var error, record;
406
- error = this.validate();
407
- if (error) {
408
- this.trigger('error', error);
409
- return false;
417
+ if (options == null) options = {};
418
+ if (options.validate !== false) {
419
+ error = this.validate();
420
+ if (error) {
421
+ this.trigger('error', error);
422
+ return false;
423
+ }
410
424
  }
411
- this.trigger('beforeSave');
412
- record = this.newRecord ? this.create() : this.update();
413
- this.trigger('save');
425
+ this.trigger('beforeSave', options);
426
+ record = this.isNew() ? this.create(options) : this.update(options);
427
+ this.trigger('save', options);
414
428
  return record;
415
429
  };
430
+
416
431
  Model.prototype.updateAttribute = function(name, value) {
417
432
  this[name] = value;
418
433
  return this.save();
419
434
  };
420
- Model.prototype.updateAttributes = function(atts) {
435
+
436
+ Model.prototype.updateAttributes = function(atts, options) {
421
437
  this.load(atts);
422
- return this.save();
438
+ return this.save(options);
423
439
  };
440
+
424
441
  Model.prototype.changeID = function(id) {
425
442
  var records;
426
- this.ids.push(this.id);
427
443
  records = this.constructor.records;
428
444
  records[id] = records[this.id];
429
445
  delete records[this.id];
430
446
  this.id = id;
431
447
  return this.save();
432
448
  };
433
- Model.prototype.destroy = function() {
434
- this.trigger('beforeDestroy');
449
+
450
+ Model.prototype.destroy = function(options) {
451
+ if (options == null) options = {};
452
+ this.trigger('beforeDestroy', options);
435
453
  delete this.constructor.records[this.id];
454
+ delete this.constructor.crecords[this.cid];
436
455
  this.destroyed = true;
437
- this.trigger('destroy');
438
- this.trigger('change', 'destroy');
456
+ this.trigger('destroy', options);
457
+ this.trigger('change', 'destroy', options);
439
458
  this.unbind();
440
459
  return this;
441
460
  };
461
+
442
462
  Model.prototype.dup = function(newRecord) {
443
463
  var result;
444
464
  result = new this.constructor(this.attributes());
445
465
  if (newRecord === false) {
446
- result.newRecord = this.newRecord;
466
+ result.cid = this.cid;
447
467
  } else {
448
468
  delete result.id;
449
469
  }
450
470
  return result;
451
471
  };
472
+
452
473
  Model.prototype.clone = function() {
453
474
  return Object.create(this);
454
475
  };
476
+
455
477
  Model.prototype.reload = function() {
456
478
  var original;
457
- if (this.newRecord) {
458
- return this;
459
- }
479
+ if (this.isNew()) return this;
460
480
  original = this.constructor.find(this.id);
461
481
  this.load(original.attributes());
462
482
  return original;
463
483
  };
484
+
464
485
  Model.prototype.toJSON = function() {
465
486
  return this.attributes();
466
487
  };
488
+
467
489
  Model.prototype.toString = function() {
468
490
  return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
469
491
  };
492
+
470
493
  Model.prototype.fromForm = function(form) {
471
494
  var key, result, _i, _len, _ref;
472
495
  result = {};
@@ -477,65 +500,86 @@
477
500
  }
478
501
  return this.load(result);
479
502
  };
503
+
480
504
  Model.prototype.exists = function() {
481
505
  return this.id && this.id in this.constructor.records;
482
506
  };
483
- Model.prototype.update = function() {
507
+
508
+ Model.prototype.update = function(options) {
484
509
  var clone, records;
485
- this.trigger('beforeUpdate');
510
+ this.trigger('beforeUpdate', options);
486
511
  records = this.constructor.records;
487
512
  records[this.id].load(this.attributes());
488
513
  clone = records[this.id].clone();
489
- clone.trigger('update');
490
- clone.trigger('change', 'update');
514
+ clone.trigger('update', options);
515
+ clone.trigger('change', 'update', options);
491
516
  return clone;
492
517
  };
493
- Model.prototype.create = function() {
494
- var clone, records;
495
- this.trigger('beforeCreate');
496
- if (!this.id) {
497
- this.id = guid();
498
- }
499
- this.newRecord = false;
500
- records = this.constructor.records;
501
- records[this.id] = this.dup(false);
502
- clone = records[this.id].clone();
503
- clone.trigger('create');
504
- clone.trigger('change', 'create');
518
+
519
+ Model.prototype.create = function(options) {
520
+ var clone, record;
521
+ this.trigger('beforeCreate', options);
522
+ if (!this.id) this.id = this.cid;
523
+ record = this.dup(false);
524
+ this.constructor.records[this.id] = record;
525
+ this.constructor.crecords[this.cid] = record;
526
+ clone = record.clone();
527
+ clone.trigger('create', options);
528
+ clone.trigger('change', 'create', options);
505
529
  return clone;
506
530
  };
531
+
507
532
  Model.prototype.bind = function(events, callback) {
508
- var binder, unbinder;
509
- this.constructor.bind(events, binder = __bind(function(record) {
510
- if (record && this.eql(record)) {
511
- return callback.apply(this, arguments);
512
- }
513
- }, this));
514
- this.constructor.bind('unbind', unbinder = __bind(function(record) {
515
- if (record && this.eql(record)) {
516
- this.constructor.unbind(events, binder);
517
- return this.constructor.unbind('unbind', unbinder);
533
+ var binder, unbinder,
534
+ _this = this;
535
+ this.constructor.bind(events, binder = function(record) {
536
+ if (record && _this.eql(record)) return callback.apply(_this, arguments);
537
+ });
538
+ this.constructor.bind('unbind', unbinder = function(record) {
539
+ if (record && _this.eql(record)) {
540
+ _this.constructor.unbind(events, binder);
541
+ return _this.constructor.unbind('unbind', unbinder);
518
542
  }
519
- }, this));
543
+ });
520
544
  return binder;
521
545
  };
546
+
547
+ Model.prototype.one = function(events, callback) {
548
+ var binder,
549
+ _this = this;
550
+ return binder = this.bind(events, function() {
551
+ _this.constructor.unbind(events, binder);
552
+ return callback.apply(_this);
553
+ });
554
+ };
555
+
522
556
  Model.prototype.trigger = function() {
523
557
  var args, _ref;
524
558
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
525
559
  args.splice(1, 0, this);
526
560
  return (_ref = this.constructor).trigger.apply(_ref, args);
527
561
  };
562
+
528
563
  Model.prototype.unbind = function() {
529
564
  return this.trigger('unbind');
530
565
  };
566
+
531
567
  return Model;
532
- })();
533
- Controller = (function() {
534
- __extends(Controller, Module);
568
+
569
+ })(Module);
570
+
571
+ Controller = (function(_super) {
572
+
573
+ __extends(Controller, _super);
574
+
535
575
  Controller.include(Events);
576
+
536
577
  Controller.include(Log);
578
+
537
579
  Controller.prototype.eventSplitter = /^(\S+)\s*(.*)$/;
580
+
538
581
  Controller.prototype.tag = 'div';
582
+
539
583
  function Controller(options) {
540
584
  this.release = __bind(this.release, this);
541
585
  var key, value, _ref;
@@ -545,30 +589,20 @@
545
589
  value = _ref[key];
546
590
  this[key] = value;
547
591
  }
548
- if (!this.el) {
549
- this.el = document.createElement(this.tag);
550
- }
592
+ if (!this.el) this.el = document.createElement(this.tag);
551
593
  this.el = $(this.el);
552
- if (this.className) {
553
- this.el.addClass(this.className);
554
- }
594
+ if (this.className) this.el.addClass(this.className);
595
+ if (this.attributes) this.el.attr(this.attributes);
555
596
  this.release(function() {
556
597
  return this.el.remove();
557
598
  });
558
- if (!this.events) {
559
- this.events = this.constructor.events;
560
- }
561
- if (!this.elements) {
562
- this.elements = this.constructor.elements;
563
- }
564
- if (this.events) {
565
- this.delegateEvents();
566
- }
567
- if (this.elements) {
568
- this.refreshElements();
569
- }
599
+ if (!this.events) this.events = this.constructor.events;
600
+ if (!this.elements) this.elements = this.constructor.elements;
601
+ if (this.events) this.delegateEvents();
602
+ if (this.elements) this.refreshElements();
570
603
  Controller.__super__.constructor.apply(this, arguments);
571
604
  }
605
+
572
606
  Controller.prototype.release = function(callback) {
573
607
  if (typeof callback === 'function') {
574
608
  return this.bind('release', callback);
@@ -576,25 +610,30 @@
576
610
  return this.trigger('release');
577
611
  }
578
612
  };
613
+
579
614
  Controller.prototype.$ = function(selector) {
580
615
  return $(selector, this.el);
581
616
  };
617
+
582
618
  Controller.prototype.delegateEvents = function() {
583
619
  var eventName, key, match, method, selector, _ref, _results;
584
620
  _ref = this.events;
585
621
  _results = [];
586
622
  for (key in _ref) {
587
623
  method = _ref[key];
588
- if (typeof method !== 'function') {
589
- method = this.proxy(this[method]);
590
- }
624
+ if (typeof method !== 'function') method = this.proxy(this[method]);
591
625
  match = key.match(this.eventSplitter);
592
626
  eventName = match[1];
593
627
  selector = match[2];
594
- _results.push(selector === '' ? this.el.bind(eventName, method) : this.el.delegate(selector, eventName, method));
628
+ if (selector === '') {
629
+ _results.push(this.el.bind(eventName, method));
630
+ } else {
631
+ _results.push(this.el.delegate(selector, eventName, method));
632
+ }
595
633
  }
596
634
  return _results;
597
635
  };
636
+
598
637
  Controller.prototype.refreshElements = function() {
599
638
  var key, value, _ref, _results;
600
639
  _ref = this.elements;
@@ -605,14 +644,17 @@
605
644
  }
606
645
  return _results;
607
646
  };
647
+
608
648
  Controller.prototype.delay = function(func, timeout) {
609
649
  return setTimeout(this.proxy(func), timeout || 0);
610
650
  };
651
+
611
652
  Controller.prototype.html = function(element) {
612
653
  this.el.html(element.el || element);
613
654
  this.refreshElements();
614
655
  return this.el;
615
656
  };
657
+
616
658
  Controller.prototype.append = function() {
617
659
  var e, elements, _ref;
618
660
  elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
@@ -629,11 +671,13 @@
629
671
  this.refreshElements();
630
672
  return this.el;
631
673
  };
674
+
632
675
  Controller.prototype.appendTo = function(element) {
633
676
  this.el.appendTo(element.el || element);
634
677
  this.refreshElements();
635
678
  return this.el;
636
679
  };
680
+
637
681
  Controller.prototype.prepend = function() {
638
682
  var e, elements, _ref;
639
683
  elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
@@ -650,19 +694,24 @@
650
694
  this.refreshElements();
651
695
  return this.el;
652
696
  };
697
+
653
698
  Controller.prototype.replace = function(element) {
654
699
  var previous, _ref;
655
- _ref = [this.el, element.el || element], previous = _ref[0], this.el = _ref[1];
700
+ _ref = [this.el, $(element.el || element)], previous = _ref[0], this.el = _ref[1];
656
701
  previous.replaceWith(this.el);
657
702
  this.delegateEvents();
658
703
  this.refreshElements();
659
704
  return this.el;
660
705
  };
706
+
661
707
  return Controller;
662
- })();
663
- $ = this.jQuery || this.Zepto || function(element) {
708
+
709
+ })(Module);
710
+
711
+ $ = (typeof window !== "undefined" && window !== null ? window.jQuery : void 0) || (typeof window !== "undefined" && window !== null ? window.Zepto : void 0) || function(element) {
664
712
  return element;
665
713
  };
714
+
666
715
  if (typeof Object.create !== 'function') {
667
716
  Object.create = function(o) {
668
717
  var Func;
@@ -671,81 +720,89 @@
671
720
  return new Func();
672
721
  };
673
722
  }
723
+
674
724
  isArray = function(value) {
675
725
  return Object.prototype.toString.call(value) === '[object Array]';
676
726
  };
727
+
677
728
  isBlank = function(value) {
678
729
  var key;
679
- if (!value) {
680
- return true;
681
- }
730
+ if (!value) return true;
682
731
  for (key in value) {
683
732
  return false;
684
733
  }
685
734
  return true;
686
735
  };
736
+
687
737
  makeArray = function(args) {
688
738
  return Array.prototype.slice.call(args, 0);
689
739
  };
690
- guid = function() {
691
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
692
- var r, v;
693
- r = Math.random() * 16 | 0;
694
- v = c === 'x' ? r : r & 3 | 8;
695
- return v.toString(16);
696
- }).toUpperCase();
697
- };
740
+
698
741
  Spine = this.Spine = {};
699
- if (typeof module !== "undefined" && module !== null) {
700
- module.exports = Spine;
701
- }
702
- Spine.version = '1.0.3';
742
+
743
+ if (typeof module !== "undefined" && module !== null) module.exports = Spine;
744
+
745
+ Spine.version = '1.0.5';
746
+
703
747
  Spine.isArray = isArray;
748
+
704
749
  Spine.isBlank = isBlank;
750
+
705
751
  Spine.$ = $;
752
+
706
753
  Spine.Events = Events;
754
+
707
755
  Spine.Log = Log;
756
+
708
757
  Spine.Module = Module;
758
+
709
759
  Spine.Controller = Controller;
760
+
710
761
  Spine.Model = Model;
762
+
711
763
  Module.extend.call(Spine, Events);
764
+
712
765
  Module.create = Module.sub = Controller.create = Controller.sub = Model.sub = function(instances, statics) {
713
766
  var result;
714
- result = (function() {
715
- __extends(result, this);
767
+ result = (function(_super) {
768
+
769
+ __extends(result, _super);
770
+
716
771
  function result() {
717
772
  result.__super__.constructor.apply(this, arguments);
718
773
  }
774
+
719
775
  return result;
720
- }).call(this);
721
- if (instances) {
722
- result.include(instances);
723
- }
724
- if (statics) {
725
- result.extend(statics);
726
- }
727
- if (typeof result.unbind === "function") {
728
- result.unbind();
729
- }
776
+
777
+ })(this);
778
+ if (instances) result.include(instances);
779
+ if (statics) result.extend(statics);
780
+ if (typeof result.unbind === "function") result.unbind();
730
781
  return result;
731
782
  };
783
+
732
784
  Model.setup = function(name, attributes) {
733
785
  var Instance;
734
- if (attributes == null) {
735
- attributes = [];
736
- }
737
- Instance = (function() {
738
- __extends(Instance, this);
786
+ if (attributes == null) attributes = [];
787
+ Instance = (function(_super) {
788
+
789
+ __extends(Instance, _super);
790
+
739
791
  function Instance() {
740
792
  Instance.__super__.constructor.apply(this, arguments);
741
793
  }
794
+
742
795
  return Instance;
743
- }).call(this);
796
+
797
+ })(this);
744
798
  Instance.configure.apply(Instance, [name].concat(__slice.call(attributes)));
745
799
  return Instance;
746
800
  };
801
+
747
802
  Module.init = Controller.init = Model.init = function(a1, a2, a3, a4, a5) {
748
803
  return new this(a1, a2, a3, a4, a5);
749
804
  };
805
+
750
806
  Spine.Class = Module;
807
+
751
808
  }).call(this);