ende 0.3.13 → 0.4.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.
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;