spine-rails 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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);