ende 0.3.13 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/component.json +7 -0
  3. data/lib/assets/javascripts/aura/extensions/devise.js.coffee +2 -2
  4. data/lib/assets/javascripts/aura/extensions/loader.js.coffee +13 -11
  5. data/lib/assets/javascripts/aura/extensions/mask.js.coffee +54 -40
  6. data/lib/assets/javascripts/aura/extensions/mediator.js +5 -3
  7. data/lib/assets/javascripts/aura/extensions/models.js.coffee.erb +2 -2
  8. data/lib/assets/javascripts/aura/extensions/rivets/accounting.js.coffee +7 -1
  9. data/lib/assets/javascripts/aura/extensions/rivets/formatters.js.coffee +5 -1
  10. data/lib/assets/javascripts/aura/extensions/rivets.js.coffee +47 -29
  11. data/lib/assets/javascripts/aura/extensions/routes.js.coffee +10 -5
  12. data/lib/assets/javascripts/aura/extensions/states.js.coffee +2 -2
  13. data/lib/assets/javascripts/aura/extensions/widget/eventable.js.coffee +18 -19
  14. data/lib/assets/javascripts/aura/extensions/widget/lifecycleable.js.coffee +15 -10
  15. data/lib/assets/javascripts/config/initializers/jquery.js.coffee +2 -1
  16. data/lib/assets/javascripts/config/initializers/requirejs.js.coffee +3 -4
  17. data/lib/assets/javascripts/config/initializers.js.coffee +3 -0
  18. data/lib/assets/javascripts/config/load_components.js.coffee +106 -83
  19. data/lib/assets/javascripts/ende.js.coffee +13 -4
  20. data/lib/assets/javascripts/widgets/authenticator/presenter.js.coffee +3 -2
  21. data/lib/assets/javascripts/widgets/dialog/main.js.coffee +7 -3
  22. data/lib/assets/javascripts/widgets/support/main.js.coffee +3 -4
  23. data/lib/assets/javascripts/widgets/viewer/main.js.coffee +35 -103
  24. data/lib/assets/javascripts/widgets/viewer/presenters/default.js.coffee +2 -4
  25. data/lib/ende/version.rb +1 -1
  26. data/vendor/assets/components/build.js +30877 -0
  27. data/vendor/assets/components/ende_build.js +2487 -148
  28. data/vendor/assets/components/indemma_with_none.js +30553 -0
  29. data/vendor/assets/javascripts/spin/spin.js +349 -0
  30. data/vendor/components/indefinido-indemma/.gitignore +3 -0
  31. data/vendor/components/indefinido-indemma/.ruby-gemset +1 -1
  32. data/vendor/components/indefinido-indemma/.ruby-version +1 -1
  33. data/vendor/components/indefinido-indemma/build/development.js +17 -14
  34. data/vendor/components/indefinido-indemma/build/release.js +213 -148
  35. data/vendor/components/indefinido-indemma/build/test.js +213 -148
  36. data/vendor/components/indefinido-indemma/component.json +3 -1
  37. data/vendor/components/indefinido-indemma/karma.conf.js +50 -60
  38. data/vendor/components/indefinido-indemma/lib/record/associable.js +17 -17
  39. data/vendor/components/indefinido-indemma/lib/record/persistable.js +8 -1
  40. data/vendor/components/indefinido-indemma/lib/record/queryable.js +3 -0
  41. data/vendor/components/indefinido-indemma/lib/record/resource.js +25 -45
  42. data/vendor/components/indefinido-indemma/lib/record/restfulable.js +82 -28
  43. data/vendor/components/indefinido-indemma/lib/record/scopable.js +28 -2
  44. data/vendor/components/indefinido-indemma/lib/record/storable.js +1 -1
  45. data/vendor/components/indefinido-indemma/lib/record/validatable.js +15 -23
  46. data/vendor/components/indefinido-indemma/lib/record/validations/associated.js +3 -5
  47. data/vendor/components/indefinido-indemma/lib/record/validations/confirmation.js +3 -5
  48. data/vendor/components/indefinido-indemma/lib/record/validations/cpf.js +5 -7
  49. data/vendor/components/indefinido-indemma/lib/record/validations/presence.js +3 -5
  50. data/vendor/components/indefinido-indemma/lib/record/validations/remote.js +3 -7
  51. data/vendor/components/indefinido-indemma/lib/record/validations/type.js +2 -2
  52. data/vendor/components/indefinido-indemma/lib/record/validations/validatorable.js +12 -0
  53. data/vendor/components/indefinido-indemma/package.json +9 -0
  54. data/vendor/components/indefinido-indemma/spec/record/restfulable_spec.js +12 -0
  55. data/vendor/components/indefinido-indemma/spec/record/validatable_spec.js +4 -4
  56. data/vendor/components/indefinido-indemma/spec/record/validations/associated_spec.js +2 -2
  57. data/vendor/components/indefinido-indemma/src/lib/record/associable.coffee +44 -20
  58. data/vendor/components/indefinido-indemma/src/lib/record/persistable.coffee +7 -2
  59. data/vendor/components/indefinido-indemma/src/lib/record/queryable.coffee +1 -0
  60. data/vendor/components/indefinido-indemma/src/lib/record/resource.coffee +32 -32
  61. data/vendor/components/indefinido-indemma/src/lib/record/restfulable.coffee +79 -22
  62. data/vendor/components/indefinido-indemma/src/lib/record/scopable.coffee +27 -8
  63. data/vendor/components/indefinido-indemma/src/lib/record/storable.coffee +1 -1
  64. data/vendor/components/indefinido-indemma/src/lib/record/validatable.coffee +20 -19
  65. data/vendor/components/indefinido-indemma/src/lib/record/validations/associated.coffee +3 -5
  66. data/vendor/components/indefinido-indemma/src/lib/record/validations/confirmation.coffee +2 -4
  67. data/vendor/components/indefinido-indemma/src/lib/record/validations/cpf.coffee +4 -5
  68. data/vendor/components/indefinido-indemma/src/lib/record/validations/presence.coffee +2 -5
  69. data/vendor/components/indefinido-indemma/src/lib/record/validations/remote.coffee +3 -7
  70. data/vendor/components/indefinido-indemma/src/lib/record/validations/type.coffee +2 -3
  71. data/vendor/components/indefinido-indemma/src/lib/record/validations/validatorable.coffee +5 -0
  72. data/vendor/components/indefinido-indemma/src/spec/record/restfulable_spec.coffee +8 -0
  73. data/vendor/components/indefinido-indemma/src/spec/record/validatable_spec.coffee +4 -4
  74. data/vendor/components/indefinido-indemma/src/spec/record/validations/associated_spec.coffee +2 -2
  75. metadata +9 -3
  76. data/lib/assets/javascripts/aura/extensions/rivets/formatters.js.coffee~ +0 -0
@@ -2,7 +2,7 @@
2
2
  "name": "indemma",
3
3
  "repo": "indefinido/indemma",
4
4
  "description": "Indemma (mind picture = memory), client side ES5 observable REST model",
5
- "version": "0.1.5",
5
+ "version": "0.1.9",
6
6
  "keywords": [],
7
7
  "dependencies": {
8
8
  "pluma/assimilate": "0.3.0",
@@ -19,6 +19,7 @@
19
19
  "vendor/stampit.js",
20
20
  "vendor/sinon.js",
21
21
  "vendor/owl/pluralize.js",
22
+
22
23
  "lib/record.js",
23
24
  "lib/record/associable.js",
24
25
  "lib/record/persistable.js",
@@ -30,6 +31,7 @@
30
31
  "lib/record/scopable.js",
31
32
  "lib/record/maid.js",
32
33
  "lib/record/translationable.js",
34
+ "lib/record/validations/validatorable.js",
33
35
  "lib/record/validations/confirmation.js",
34
36
  "lib/record/validations/associated.js",
35
37
  "lib/record/validations/presence.js",
@@ -1,86 +1,76 @@
1
1
  // Karma configuration
2
- // Generated on Mon May 27 2013 16:00:28 GMT-0300 (BRT)
3
2
 
3
+ module.exports = function(config) {
4
+ config.set({
4
5
 
5
- // base path, that will be used to resolve files and exclude
6
- basePath = '';
6
+ // base path, that will be used to resolve files and exclude
7
+ basePath: '',
7
8
 
8
- // list of files / patterns to load in the browser
9
- files = [
10
9
 
11
- // Test environment
12
- MOCHA,
13
- MOCHA_ADAPTER,
14
- 'vendor/sinon.js',
10
+ // frameworks to use
11
+ frameworks: ['mocha'],
15
12
 
16
- // Test dependencies
17
- 'build/test.js',
18
- 'spec/support/**/*.js',
19
13
 
20
- // Test Source files
21
- 'spec/spec_helper.js',
22
- 'spec/**/*.js'
23
- ];
14
+ // list of files / patterns to load in the browser
15
+ files: [
16
+ 'vendor/sinon.js',
17
+ 'build/test.js',
18
+ 'spec/support/**/*.js',
19
+ 'spec/spec_helper.js',
20
+ 'spec/**/*.js'
21
+ ],
24
22
 
23
+ // list of files to excudle
24
+ exclude: [
25
+ 'spec/coverage/**/*.js'
26
+ ],
25
27
 
26
- // list of files to exclude
27
- exclude = [
28
- 'spec/coverage'
29
- ];
28
+ client: {
29
+ mocha: {
30
+ ui: 'bdd'
31
+ }
32
+ },
30
33
 
31
34
 
32
- // test results reporter to use
33
- // possible values: 'dots', 'progress', 'junit'
34
- reporters = ['progress', 'coverage'];
35
+ // test results reporter to use
36
+ // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
37
+ reporters: ['progress'],
35
38
 
36
39
 
37
- // web server port
38
- port = 9876;
40
+ // web server port
41
+ port: 9876,
39
42
 
40
43
 
41
- // cli runner port
42
- runnerPort = 9100;
44
+ // enable / disable colors in the output (reporters and logs)
45
+ colors: true,
43
46
 
44
47
 
45
- // enable / disable colors in the output (reporters and logs)
46
- colors = true;
48
+ // level of logging
49
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
50
+ logLevel: config.LOG_INFO,
47
51
 
48
52
 
49
- // level of logging
50
- // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
51
- logLevel = LOG_INFO;
53
+ // enable / disable watching file and executing tests whenever any file changes
54
+ autoWatch: true,
52
55
 
53
56
 
54
- // enable / disable watching file and executing tests whenever any file changes
55
- autoWatch = true;
57
+ // Start these browsers, currently available:
58
+ // - Chrome
59
+ // - ChromeCanary
60
+ // - Firefox
61
+ // - Opera (has to be installed with `npm install karma-opera-launcher`)
62
+ // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
63
+ // - PhantomJS
64
+ // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
65
+ browsers: ['Chrome'],
56
66
 
57
67
 
58
- // Start these browsers, currently available:
59
- // - Chrome
60
- // - ChromeCanary
61
- // - Firefox
62
- // - Opera
63
- // - Safari (only Mac)
64
- // - PhantomJS
65
- // - IE (only Windows)
66
- browsers = ['Chrome'];
68
+ // If browser does not capture in given timeout [ms], kill it
69
+ captureTimeout: 60000,
67
70
 
68
71
 
69
- // If browser does not capture in given timeout [ms], kill it
70
- captureTimeout = 600000;
71
-
72
-
73
- // Continuous Integration mode
74
- // if true, it capture browsers, run tests and exit
75
- singleRun = false;
76
-
77
- // Coverage preprocessors
78
- preprocessors = {
79
- '**/lib/*.js': 'coverage'
72
+ // Continuous Integration mode
73
+ // if true, it capture browsers, run tests and exit
74
+ singleRun: false
75
+ });
80
76
  };
81
-
82
- // Converage configuration
83
- coverageReporter = {
84
- type : 'html',
85
- dir : 'spec/coverage'
86
- }
@@ -79,26 +79,22 @@ singular = {
79
79
  subscribers = {
80
80
  belongs_to: {
81
81
  foreign_key: function(resource_id) {
82
- var associated, association_name, current_resource_id, resource, _ref;
82
+ var association_name, current_resource_id, resource, _ref;
83
83
 
84
84
  association_name = this.resource.toString();
85
- if (resource_id === null || resource_id === void 0) {
85
+ if (!resource_id) {
86
86
  this.dirty = true;
87
87
  this.owner[association_name] = resource_id;
88
88
  return resource_id;
89
89
  }
90
- current_resource_id = (_ref = this.owner[association_name]) != null ? _ref._id : void 0;
90
+ current_resource_id = (_ref = this.owner.observed[association_name]) != null ? _ref._id : void 0;
91
91
  if (resource_id !== current_resource_id) {
92
92
  resource = model[association_name];
93
93
  if (!resource) {
94
94
  console.warn("subscribers.belongs_to.foreign_key: associated factory not found for model: " + association_name);
95
95
  return resource_id;
96
96
  }
97
- associated = resource.find(resource_id);
98
- associated || (associated = resource({
99
- _id: resource_id
100
- }));
101
- this.owner.observed[association_name] = associated;
97
+ this.owner.observed[association_name] = null;
102
98
  }
103
99
  return resource_id;
104
100
  },
@@ -136,10 +132,12 @@ modifiers = {
136
132
  return associated;
137
133
  }
138
134
  associated = resource.find(associated_id || associated._id);
135
+ if (associated) {
136
+ return _this.owner.observed[association_name] = associated;
137
+ }
139
138
  associated || (associated = resource({
140
139
  _id: associated_id
141
140
  }));
142
- resource.storage.store(associated._id, associated);
143
141
  associated.reload();
144
142
  return _this.owner.observed[association_name] = associated;
145
143
  },
@@ -161,8 +159,8 @@ callbacks = {
161
159
  for (_i = 0, _len = association_names.length; _i < _len; _i++) {
162
160
  association_name = association_names[_i];
163
161
  associations_attributes = this["" + association_name + "_attributes"];
162
+ association = this[model.pluralize(association_name)];
164
163
  if (associations_attributes && associations_attributes.length) {
165
- association = this[model.pluralize(association_name)];
166
164
  if (!association) {
167
165
  message = "has_many.nest_attributes: Association not found for " + association_name + ". \n";
168
166
  message += "did you set it on model declaration? \n has_many: " + association_name + " ";
@@ -252,7 +250,7 @@ associable = {
252
250
  return true;
253
251
  },
254
252
  create_after_hooks: function(definition) {
255
- var association_name, association_proxy, old_resource_id, options, resource, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
253
+ var association_attributes, association_name, association_proxy, old_dirty, old_resource_id, options, resource, _i, _j, _k, _len, _len1, _len2, _name, _ref, _ref1, _ref2, _results;
256
254
 
257
255
  options = model[this.resource.name || this.resource.toString()];
258
256
  if (options.has_many) {
@@ -265,6 +263,11 @@ associable = {
265
263
  parent: this
266
264
  };
267
265
  association_name = model.pluralize(resource);
266
+ association_attributes = this[association_name] || [];
267
+ this[_name = "" + association_name + "_attributes"] || (this[_name] = []);
268
+ if (association_attributes.length) {
269
+ this["" + association_name + "_attributes"] = this["" + association_name + "_attributes"].concat(association_attributes);
270
+ }
268
271
  this[association_name] = $.extend(association_proxy, plural);
269
272
  }
270
273
  this.after('saved', callbacks.has_many.update_association);
@@ -300,15 +303,12 @@ associable = {
300
303
  this["build_" + resource] = $.proxy(singular.build, association_proxy);
301
304
  this["create_" + resource] = $.proxy(singular.create, association_proxy);
302
305
  old_resource_id = this["" + resource + "_id"];
306
+ old_dirty = this.dirty;
303
307
  this["" + resource + "_id"] = null;
304
308
  this.subscribe("" + resource + "_id", $.proxy(subscribers.belongs_to.foreign_key, association_proxy));
305
309
  this.subscribe(resource.toString(), $.proxy(subscribers.belongs_to.associated_changed, association_proxy));
306
- this.resource_id = old_resource_id;
307
- if (this["" + resource + "_id"] && !this[resource]) {
308
- _results.push(this.publish("" + resource + "_id", this["" + resource + "_id"]));
309
- } else {
310
- _results.push(void 0);
311
- }
310
+ this["" + resource + "_id"] = old_resource_id;
311
+ _results.push(this.dirty = old_dirty);
312
312
  }
313
313
  return _results;
314
314
  }
@@ -16,7 +16,14 @@ handlers = {
16
16
  persistable = {
17
17
  record: {
18
18
  after_initialize: function() {
19
- return this.after('saved', handlers.store_after_saved);
19
+ var storage;
20
+
21
+ if (this._id) {
22
+ storage = model[this.resource.toString()].storage;
23
+ return storage.store(this._id, this);
24
+ } else {
25
+ return this.after('saved', handlers.store_after_saved);
26
+ }
20
27
  }
21
28
  }
22
29
  };
@@ -9,6 +9,9 @@ stampit = require('../../vendor/stampit');
9
9
  queryable = {
10
10
  storage: storable(),
11
11
  find: function(key) {
12
+ if (!key) {
13
+ throw new TypeError("InvalidFind: resource.find was called with a falsey value");
14
+ }
12
15
  return this.storage.store(key);
13
16
  },
14
17
  all: function() {
@@ -1,4 +1,4 @@
1
- var model, resource, resourceable, stampit;
1
+ var descriptors, model, resource, resourceable, stampit;
2
2
 
3
3
  stampit = require('../../vendor/stampit');
4
4
 
@@ -25,34 +25,11 @@ resource = stampit({
25
25
  return this;
26
26
  });
27
27
 
28
- resourceable = {
29
- pluralize: function(word, count, plural) {
30
- if (!(word && word.length)) {
31
- throw new TypeError("Invalid string passed to pluralize '" + word + "'");
32
- }
33
- if (word.indexOf('s') !== word.length - 1) {
34
- return owl.pluralize(word, count, plural);
35
- } else {
36
- return word;
37
- }
38
- },
39
- singularize: function(word) {
40
- if (!(word && word.length)) {
41
- throw new TypeError("Invalid string passed to singularize '" + word + "'");
42
- }
43
- if (word.lastIndexOf('s') === word.length - 1) {
44
- return word.substring(0, word.length - 1);
45
- } else {
46
- return word;
47
- }
48
- },
28
+ descriptors = {
49
29
  route: {
50
30
  get: function() {
51
31
  var route;
52
32
 
53
- if (this.initial_route != null) {
54
- return this.initial_route;
55
- }
56
33
  if (typeof this.resource === 'string') {
57
34
  this.resource = {
58
35
  name: this.resource
@@ -66,33 +43,36 @@ resourceable = {
66
43
  route += this.resource.scope + '/';
67
44
  }
68
45
  route += this.resource.singular ? this.resource.name : model.pluralize(this.resource.name);
69
- this.initial_route = route;
70
- return route;
46
+ return this.route = route;
71
47
  },
72
- set: function(value) {
73
- return this.initial_route = value;
48
+ configurable: true
49
+ }
50
+ };
51
+
52
+ resourceable = {
53
+ pluralize: function(word, count, plural) {
54
+ if (!(word && word.length)) {
55
+ throw new TypeError("Invalid string passed to pluralize '" + word + "'");
56
+ }
57
+ if (word.indexOf('s') !== word.length - 1) {
58
+ return owl.pluralize(word, count, plural);
59
+ } else {
60
+ return word;
74
61
  }
75
62
  },
76
- parent_id: {
77
- get: function() {
78
- if (this[this.parent_resource]) {
79
- return this[this.parent_resource]._id;
80
- }
81
- },
82
- set: function() {
83
- return console.error('Warning changing associations throught parent_id not allowed for security and style guide purposes');
63
+ singularize: function(word) {
64
+ if (!(word && word.length)) {
65
+ throw new TypeError("Invalid string passed to singularize '" + word + "'");
66
+ }
67
+ if (word.lastIndexOf('s') === word.length - 1) {
68
+ return word.substring(0, word.length - 1);
69
+ } else {
70
+ return word;
84
71
  }
85
72
  },
86
73
  initialize: function() {
87
74
  var resource_definition, _ref;
88
75
 
89
- if (this.parent_resource) {
90
- Object.defineProperty(this, "" + this.parent_resource + "_id", {
91
- value: resourceable.parent_id,
92
- configurable: true,
93
- enumerable: true
94
- });
95
- }
96
76
  resource_definition = {};
97
77
  if (typeof this.resource === 'string') {
98
78
  resource_definition = {
@@ -105,7 +85,7 @@ resourceable = {
105
85
  }
106
86
  resource_definition.parent = this.parent_resource;
107
87
  this.resource = resource(resource_definition);
108
- return (_ref = this.route) != null ? _ref : Object.defineProperty(this, 'route', resourceable.route);
88
+ return (_ref = this.route) != null ? _ref : Object.defineProperty(this, 'route', descriptors.route);
109
89
  }
110
90
  };
111
91
 
@@ -1,4 +1,4 @@
1
- var $, merge, model, observable, record, rest, restful, type, util,
1
+ var $, merge, model, observable, record, rest, restful, root, type, util,
2
2
  __slice = [].slice;
3
3
 
4
4
  merge = require('assimilate').withStrategy('deep');
@@ -11,15 +11,17 @@ $ = require('jquery');
11
11
 
12
12
  rest = require('./rest.js');
13
13
 
14
+ root = typeof exports !== "undefined" && exports !== null ? exports : this;
15
+
14
16
  util = {
15
17
  model: {
16
- map: function(models) {
17
- var model, _i, _len, _results;
18
+ map: function(records) {
19
+ var record, _i, _len, _results;
18
20
 
19
21
  _results = [];
20
- for (_i = 0, _len = models.length; _i < _len; _i++) {
21
- model = models[_i];
22
- _results.push(this(model));
22
+ for (_i = 0, _len = records.length; _i < _len; _i++) {
23
+ record = records[_i];
24
+ _results.push(this(record));
23
25
  }
24
26
  return _results;
25
27
  }
@@ -51,15 +53,15 @@ restful = {
51
53
  }
52
54
  return $.when.apply($, savings);
53
55
  },
54
- all: function(conditions, callback) {
56
+ all: function(conditions, doned, failed) {
55
57
  if (conditions == null) {
56
58
  conditions = {};
57
59
  }
58
60
  if (typeof conditions === 'function') {
59
- callback = conditions;
61
+ doned = conditions;
60
62
  conditions = {};
61
63
  }
62
- return $.when(rest.get.call(this, conditions)).then(util.model.map).done(callback);
64
+ return $.when(rest.get.call(this, conditions)).then(util.model.map).done(doned).fail(failed);
63
65
  },
64
66
  first: function(conditions, callback) {
65
67
  var namespaced;
@@ -77,15 +79,21 @@ restful = {
77
79
  return this.all(conditions, callback);
78
80
  },
79
81
  get: function(action, data) {
80
- var old_route, payload, promise, resource, route;
82
+ var default_route, old_route, payload, promise, resource;
81
83
 
82
84
  if (data == null) {
83
85
  data = {};
84
86
  }
85
87
  old_route = this.route;
86
- this.route = "/" + (model.pluralize(this.resource.name));
88
+ default_route = "/" + (model.pluralize(this.resource.name));
89
+ if (default_route !== this.route) {
90
+ this.route = default_route;
91
+ }
87
92
  if (action) {
88
- this.route += "/" + action;
93
+ Object.defineProperty(this, 'route', {
94
+ value: "" + default_route + "/" + action,
95
+ configurable: true
96
+ });
89
97
  }
90
98
  resource = data.resource;
91
99
  if (data && data.json) {
@@ -97,13 +105,19 @@ restful = {
97
105
  data[resource] = payload;
98
106
  }
99
107
  promise = rest.get.call(this, data);
100
- route = old_route;
108
+ Object.defineProperty(this, 'route', {
109
+ value: old_route,
110
+ configurable: true
111
+ });
101
112
  return promise;
102
113
  },
103
114
  put: rest.put,
104
115
  "delete": rest["delete"]
105
116
  },
106
117
  record: {
118
+ ready: function(callback) {
119
+ return callback.call(this);
120
+ },
107
121
  reload: function() {
108
122
  var data, param, params, promise, _i, _len;
109
123
 
@@ -115,6 +129,11 @@ restful = {
115
129
  promise = rest.get.call(this, data || {});
116
130
  promise.done(this.assign_attributes);
117
131
  promise.fail(this.failed);
132
+ this.reloading = promise;
133
+ this.ready = function() {
134
+ console.warn("resource.ready was deprecated, please use resource.reloading.done");
135
+ return promise.done.apply(promise, arguments);
136
+ };
118
137
  for (_i = 0, _len = params.length; _i < _len; _i++) {
119
138
  param = params[_i];
120
139
  promise.done(param);
@@ -122,7 +141,7 @@ restful = {
122
141
  return promise;
123
142
  },
124
143
  assign_attributes: function(attributes) {
125
- var association, association_attributes, association_name, associations_attributes, attribute, message, singular_resource, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _results;
144
+ var association, association_attributes, association_name, associations_attributes, attribute, message, name, singular_resource, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _results;
126
145
 
127
146
  _ref = model[this.resource.toString()].has_many;
128
147
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -167,9 +186,18 @@ restful = {
167
186
  }
168
187
  }
169
188
  _results = [];
170
- for (attribute in attributes) {
171
- if (attribute !== this[attribute]) {
172
- _results.push(this[attribute] = attributes[attribute]);
189
+ for (name in attributes) {
190
+ attribute = attributes[name];
191
+ if (attribute !== this[name]) {
192
+ if (type(attribute) === 'object') {
193
+ if (JSON.stringify(attribute) !== JSON.stringify(this[name])) {
194
+ _results.push(this[name] = attributes[name]);
195
+ } else {
196
+ _results.push(void 0);
197
+ }
198
+ } else {
199
+ _results.push(this[name] = attributes[name]);
200
+ }
173
201
  }
174
202
  }
175
203
  return _results;
@@ -190,18 +218,23 @@ restful = {
190
218
  saving: false,
191
219
  salvation: null,
192
220
  save: function(doned, failed, data) {
193
- var salvation;
221
+ var lock, salvation;
194
222
 
223
+ lock = JSON.stringify(this.json());
195
224
  if (this.saving) {
196
- return this.salvation;
225
+ if (this.lock === lock) {
226
+ return this.salvation;
227
+ } else {
228
+ this.salvation.abort();
229
+ }
197
230
  }
198
- this.lock = JSON.stringify(this.json());
231
+ this.lock = lock;
199
232
  if (!this.dirty) {
200
233
  salvation = $.Deferred().resolveWith(this, null);
201
234
  }
235
+ this.saving = true;
202
236
  salvation || (salvation = rest[this._id ? 'put' : 'post'].call(this, data));
203
237
  this.salvation = salvation;
204
- this.saving = true;
205
238
  salvation.done(this.saved);
206
239
  salvation.fail(this.failed);
207
240
  salvation.always(function() {
@@ -217,8 +250,6 @@ restful = {
217
250
  if (this.lock === JSON.stringify(this.json())) {
218
251
  this.dirty = false;
219
252
  delete this.lock;
220
- } else {
221
- return this.save();
222
253
  }
223
254
  if (data != null) {
224
255
  this.assign_attributes(data);
@@ -244,8 +275,21 @@ restful = {
244
275
  }
245
276
  payload || (payload = xhr.responseText);
246
277
  switch (xhr.status) {
278
+ case 0:
279
+ message = status || xhr.statusText;
280
+ switch (message) {
281
+ case 'abort':
282
+ console.info("salvation probably aborted");
283
+ break;
284
+ case 'error':
285
+ console.info("server probably unreachable");
286
+ break;
287
+ default:
288
+ throw new Error('Unhandled status code for xhr');
289
+ }
290
+ break;
247
291
  case 422:
248
- definition = model[this.resource];
292
+ definition = model[this.resource.toString()];
249
293
  _ref = payload.errors;
250
294
  for (attribute_name in _ref) {
251
295
  messages = _ref[attribute_name];
@@ -270,8 +314,9 @@ restful = {
270
314
  default:
271
315
  message = "Fail in " + this.resource + ".save:\n";
272
316
  message += "Record: " + this + "\n";
273
- message += "Status: " + status + " (" + (payload.status || xhr.status) + ")\n";
317
+ message += "Status: " + status + " (" + (payload || xhr).status + ")\n";
274
318
  message += "Error : " + (payload.error || payload.message || payload);
319
+ console.log(message);
275
320
  }
276
321
  return this.saving = false;
277
322
  },
@@ -283,20 +328,27 @@ restful = {
283
328
  return JSON.stringify(serialized);
284
329
  },
285
330
  json: function(methods) {
286
- var attribute, json, name, value, _i, _len, _ref;
331
+ var attribute, definition, json, name, value, _i, _len, _ref;
287
332
 
288
333
  if (methods == null) {
289
334
  methods = {};
290
335
  }
291
336
  json = {};
337
+ definition = model[this.resource.toString()];
292
338
  for (name in this) {
293
- value = this[name];
294
- if (!(type(value) !== 'function')) {
339
+ if (!(type(value))) {
295
340
  continue;
296
341
  }
342
+ if (definition.belongs_to.indexOf(name) !== -1 && this.nested_attributes.indexOf(name) === -1) {
343
+ continue;
344
+ }
345
+ value = this[name];
297
346
  if (value == null) {
298
347
  continue;
299
348
  }
349
+ if (type(value) === 'function') {
350
+ continue;
351
+ }
300
352
  if (type(value) === 'object') {
301
353
  if (value.toJSON != null) {
302
354
  json[name] = value.toJSON(methods[name]);
@@ -322,6 +374,8 @@ restful = {
322
374
  delete json.before_initialize;
323
375
  delete json.parent_resource;
324
376
  delete json.nested_attributes;
377
+ delete json.reloading;
378
+ delete json.ready;
325
379
  delete json.saving;
326
380
  delete json.salvation;
327
381
  delete json.sustained;