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
@@ -1,4 +1,4 @@
1
- var $, builders, defaults, extend, merge, model, record, rest, scopable, stampit,
1
+ var $, builders, defaults, extend, merge, model, observable, record, rest, scopable, stampit, util,
2
2
  __slice = [].slice;
3
3
 
4
4
  require('./restfulable');
@@ -9,12 +9,29 @@ stampit = require('../../vendor/stampit');
9
9
 
10
10
  extend = require('assimilate');
11
11
 
12
+ observable = require('observable').mixin;
13
+
12
14
  merge = extend.withStrategy('deep');
13
15
 
14
16
  $ = require('jquery');
15
17
 
16
18
  rest = require('./rest');
17
19
 
20
+ util = {
21
+ model: {
22
+ map: function(records) {
23
+ var index, record, _i, _len, _results;
24
+
25
+ _results = [];
26
+ for (index = _i = 0, _len = records.length; _i < _len; index = ++_i) {
27
+ record = records[index];
28
+ _results.push((this.build || this).call(this, record));
29
+ }
30
+ return _results;
31
+ }
32
+ }
33
+ };
34
+
18
35
  scopable = {
19
36
  builder: stampit().enclose(function() {
20
37
  return stampit.mixIn(function(name, type) {
@@ -45,14 +62,19 @@ scopable = {
45
62
  fetch: function(data, done, fail) {
46
63
  var deferred, scope;
47
64
 
65
+ if (typeof data === 'function') {
66
+ done = data;
67
+ data = {};
68
+ }
48
69
  scope = extend({}, this.scope.data);
70
+ observable.unobserve(scope);
49
71
  if (scope.noned != null) {
50
72
  deferred = $.Deferred();
51
73
  deferred.resolveWith(this, [[]]);
52
74
  } else {
53
75
  deferred = rest.get.call(this, extend(scope, data));
54
76
  }
55
- deferred.done(this.scope.then.concat(done)).fail([this.scope.fail, fail]);
77
+ deferred.then(util.model.map).done(this.scope.then.concat([done])).fail(this.scope.fail.concat([fail]));
56
78
  this.scope.clear();
57
79
  return deferred;
58
80
  },
@@ -95,6 +117,10 @@ scopable = {
95
117
  return this;
96
118
  },
97
119
  fetch: function(data, done, fail) {
120
+ if (typeof data === 'function') {
121
+ done = data;
122
+ data = null;
123
+ }
98
124
  return this.scope.fetch.call(this, data, done, fail);
99
125
  },
100
126
  forward_scopes_to_associations: function() {
@@ -23,7 +23,7 @@ storable = stampit({
23
23
  return collection[key];
24
24
  } else {
25
25
  this.writes++;
26
- value.sustained = true;
26
+ value.sustained || (value.sustained = true);
27
27
  return collection[key] = value;
28
28
  }
29
29
  },
@@ -1,8 +1,8 @@
1
- var errorsable, extensions, initializers, manager, messages, observable, root, stampit, type, validatable;
1
+ var errorsable, extensions, initializers, manager, messages, observable, root, stampit, type;
2
2
 
3
3
  require('./translationable');
4
4
 
5
- root = typeof exports !== "undefined" && exports !== null ? exports : window;
5
+ root = typeof exports !== "undefined" && exports !== null ? exports : this;
6
6
 
7
7
  stampit = require('../../vendor/stampit');
8
8
 
@@ -93,7 +93,7 @@ initializers = {
93
93
  });
94
94
  this.validated = false;
95
95
  this.subscribe('dirty', function(value) {
96
- return this.validated = false;
96
+ return value && (this.validated = false);
97
97
  });
98
98
  return Object.defineProperty(this, 'valid', {
99
99
  get: function() {
@@ -187,7 +187,12 @@ extensions = {
187
187
  this.validation.done(doned);
188
188
  this.validation.fail(failed);
189
189
  this.validation.then(function(record) {
190
- return record.validated = true;
190
+ var old_dirty;
191
+
192
+ old_dirty = record.dirty;
193
+ record.dirty = null;
194
+ record.validated || (record.validated = true);
195
+ return record.dirty = old_dirty;
191
196
  });
192
197
  return this.validation;
193
198
  }
@@ -198,15 +203,6 @@ manager = {
198
203
  validators: {}
199
204
  };
200
205
 
201
- validatable = stampit({
202
- validate: function() {
203
- throw new Error('Composed factory must override the validate method');
204
- },
205
- validate_each: function() {
206
- throw new Error('Composed factory must override the validate each method');
207
- }
208
- });
209
-
210
206
  model.mix(function(modelable) {
211
207
  jQuery.extend(modelable, extensions.model);
212
208
  jQuery.extend(modelable.record, extensions.record);
@@ -215,18 +211,14 @@ model.mix(function(modelable) {
215
211
  return model.validators = manager.validators;
216
212
  });
217
213
 
218
- root.validatable = validatable;
219
-
220
- root.manager = manager;
221
-
222
- require('./validations/confirmation');
214
+ manager.validators.confirmation = require('./validations/confirmation');
223
215
 
224
- require('./validations/associated');
216
+ manager.validators.associated = require('./validations/associated');
225
217
 
226
- require('./validations/presence');
218
+ manager.validators.presence = require('./validations/presence');
227
219
 
228
- require('./validations/remote');
220
+ manager.validators.remote = require('./validations/remote');
229
221
 
230
- require('./validations/type');
222
+ manager.validators.type = require('./validations/type');
231
223
 
232
- require('./validations/cpf');
224
+ manager.validators.cpf = require('./validations/cpf');
@@ -1,6 +1,4 @@
1
- var associationable, composed, stampit, validations;
2
-
3
- validations = require('../validatable');
1
+ var associationable, composed, stampit;
4
2
 
5
3
  stampit = require('../../../vendor/stampit');
6
4
 
@@ -23,8 +21,8 @@ associationable = stampit({
23
21
  }
24
22
  });
25
23
 
26
- composed = stampit.compose(validations.validatable, associationable);
24
+ composed = stampit.compose(require('./validatorable'), associationable);
27
25
 
28
26
  composed.definition_key = 'validates_associated';
29
27
 
30
- validations.manager.validators.association = composed;
28
+ module.exports = composed;
@@ -1,6 +1,4 @@
1
- var composed, confirmationable, stampit, validations;
2
-
3
- validations = require('../validatable');
1
+ var composed, confirmationable, stampit;
4
2
 
5
3
  stampit = require('../../../vendor/stampit');
6
4
 
@@ -12,8 +10,8 @@ confirmationable = stampit({
12
10
  }
13
11
  });
14
12
 
15
- composed = stampit.compose(validations.validatable, confirmationable);
13
+ composed = stampit.compose(require('./validatorable'), confirmationable);
16
14
 
17
15
  composed.definition_key = 'validates_confirmation_of';
18
16
 
19
- validations.manager.validators.confirmation = composed;
17
+ module.exports = composed;
@@ -1,6 +1,4 @@
1
- var composed, cpfable, stampit, validations;
2
-
3
- validations = require('../validatable');
1
+ var composed, cpfable, stampit;
4
2
 
5
3
  stampit = require('../../../vendor/stampit');
6
4
 
@@ -20,7 +18,7 @@ cpfable = stampit({
20
18
  d1 = 0;
21
19
  v = false;
22
20
  i = 0;
23
- for (i = _i = 1; _i <= 9; i = ++_i) {
21
+ for (i = _i = 0; _i <= 9; i = ++_i) {
24
22
  d1 += c.charAt(i) * (10 - i);
25
23
  }
26
24
  if (d1 === 0) {
@@ -34,7 +32,7 @@ cpfable = stampit({
34
32
  return false;
35
33
  }
36
34
  d1 *= 2;
37
- for (i = _j = 1; _j <= 9; i = ++_j) {
35
+ for (i = _j = 0; _j <= 9; i = ++_j) {
38
36
  d1 += c.charAt(i) * (11 - i);
39
37
  }
40
38
  d1 = 11 - (d1 % 11);
@@ -53,8 +51,8 @@ cpfable = stampit({
53
51
  }
54
52
  });
55
53
 
56
- composed = stampit.compose(validations.validatable, cpfable);
54
+ composed = stampit.compose(require('./validatorable'), cpfable);
57
55
 
58
56
  composed.definition_key = 'validates_cpf_format';
59
57
 
60
- validations.manager.validators.cpf = composed;
58
+ module.exports = composed;
@@ -1,6 +1,4 @@
1
- var composed, presenceable, stampit, validations;
2
-
3
- validations = require('../validatable');
1
+ var composed, presenceable, stampit;
4
2
 
5
3
  stampit = require('../../../vendor/stampit');
6
4
 
@@ -12,8 +10,8 @@ presenceable = stampit({
12
10
  }
13
11
  });
14
12
 
15
- composed = stampit.compose(validations.validatable, presenceable);
13
+ composed = stampit.compose(require('./validatorable'), presenceable);
16
14
 
17
15
  composed.definition_key = 'validates_presence_of';
18
16
 
19
- validations.manager.validators.presence = composed;
17
+ module.exports = composed;
@@ -1,8 +1,4 @@
1
- var composed, remoteable, rest, root, stampit, validations;
2
-
3
- root = typeof exports !== "undefined" && exports !== null ? exports : window;
4
-
5
- validations = require('../validatable');
1
+ var composed, remoteable, rest, stampit;
6
2
 
7
3
  rest = require('../rest');
8
4
 
@@ -65,8 +61,8 @@ remoteable = stampit({
65
61
  return this;
66
62
  });
67
63
 
68
- composed = stampit.compose(validations.validatable, remoteable);
64
+ composed = stampit.compose(require('./validatorable'), remoteable);
69
65
 
70
66
  composed.definition_key = 'validates_remotely';
71
67
 
72
- validations.manager.validators.remote = composed;
68
+ module.exports = composed;
@@ -22,8 +22,8 @@ typeable = stampit({
22
22
  }
23
23
  });
24
24
 
25
- composed = stampit.compose(validations.validatable, typeable);
25
+ composed = stampit.compose(require('./validatorable'), typeable);
26
26
 
27
27
  composed.definition_key = 'validates_type_of';
28
28
 
29
- validations.manager.validators.type = composed;
29
+ module.exports = composed;
@@ -0,0 +1,12 @@
1
+ var stampit;
2
+
3
+ stampit = require('../../../vendor/stampit');
4
+
5
+ module.exports = stampit({
6
+ validate: function() {
7
+ throw new Error('Composed factory must override the validate method');
8
+ },
9
+ validate_each: function() {
10
+ throw new Error('Composed factory must override the validate each method');
11
+ }
12
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "indemma",
3
+ "version": "0.1.7",
4
+ "devDependencies": {
5
+ "mocha": "*",
6
+ "karma": "~0.10",
7
+ "karma-mocha": "~0.1"
8
+ }
9
+ }
@@ -121,6 +121,18 @@ describe('restfulable', function() {
121
121
  belongs_to: 'person'
122
122
  });
123
123
  });
124
+ it('should not assign attribute with the same value twice', function() {
125
+ var arthur, object;
126
+
127
+ object = {};
128
+ arthur = person({
129
+ name: object
130
+ });
131
+ arthur.assign_attributes({
132
+ name: {}
133
+ });
134
+ return arthur.name.should.not.be.eq(object);
135
+ });
124
136
  return it('assigns associations properly', function() {
125
137
  var arthur, attributes, ford, marvin, search_record;
126
138
 
@@ -18,9 +18,9 @@ describe('model', function() {
18
18
  person.should.have.property('validators');
19
19
  return person.validators.should.be.an('array');
20
20
  });
21
- return describe('#()', function() {
21
+ return describe('(validates_... : ...)', function() {
22
22
  describe('validators instatiation', function() {
23
- it('should instantiate validators with prefix validates_', function() {
23
+ it('should have validators', function() {
24
24
  var validator;
25
25
 
26
26
  person = model.call({
@@ -32,9 +32,9 @@ describe('model', function() {
32
32
  validator = person.validators[0];
33
33
  return validator.should.have.property('attribute_name', 'name');
34
34
  });
35
- return it('should instantiate validators with in the key validates');
35
+ return it('should have validators with in the key validates');
36
36
  });
37
- describe('#validate_attribute', function() {
37
+ describe('.validate_attribute()', function() {
38
38
  beforeEach(function() {
39
39
  person.validators.length = 0;
40
40
  return person = model.call({
@@ -4,7 +4,7 @@ root = typeof exports !== "undefined" && exports !== null ? exports : window;
4
4
 
5
5
  require('indemma/lib/record/validatable');
6
6
 
7
- describe('model #() validates_associated', function() {
7
+ describe('model ( validates_associated: ... )', function() {
8
8
  return describe('basic usage', function() {
9
9
  var address, model, person;
10
10
 
@@ -26,7 +26,7 @@ describe('model #() validates_associated', function() {
26
26
  person.validators.length = 0;
27
27
  return address.validators.length = 0;
28
28
  });
29
- return describe('#validate', function() {
29
+ return describe('.validate()', function() {
30
30
  return it('should add error to record when fields does not match', function() {
31
31
  var arthur;
32
32
 
@@ -20,7 +20,6 @@ plural = # has_many ## TODO embeds_many
20
20
  build: (data = {}) ->
21
21
  data.parent_resource = @parent_resource
22
22
 
23
-
24
23
  # TODO Setup a before save callback to generate route when there is no id
25
24
  data.route ||= "#{@parent.route}/#{@parent._id}/#{model.pluralize @resource.toString()}" if @parent?
26
25
  throw "associable.has_many: cannot redefine route of association #{@parent_resource}.#{@resource} from #{@route} to #{data.route}" if @route isnt data.route and @route
@@ -54,15 +53,15 @@ subscribers =
54
53
  association_name = @resource.toString()
55
54
 
56
55
  # TODO faster nullifing association check
57
- # TODO only allow nullifying with null
58
- if resource_id == null or resource_id == undefined
56
+ # TODO check if its usefull to only allow disassociating with null
57
+ unless resource_id
59
58
  @dirty = true
60
59
  @owner[association_name] = resource_id
61
60
  return resource_id
62
61
 
63
62
  # TODO Discover and update inverse side of association
64
63
  # associated[@owner.resource.toString()] = @owner
65
- current_resource_id = @owner[association_name]?._id
64
+ current_resource_id = @owner.observed[association_name]?._id
66
65
  if resource_id != current_resource_id
67
66
  # Update association with blank resource that will update
68
67
  resource = model[association_name]
@@ -71,10 +70,13 @@ subscribers =
71
70
  return resource_id
72
71
 
73
72
  # TODO remote find or local find automatically, and implement find_or_initialize_by
74
- associated = resource.find resource_id
75
- associated ||= resource _id: resource_id
73
+ # this code is not needed, since the association loader already loads the associated record when trying to get it
74
+ # associated = resource.find resource_id
75
+ # associated ||= resource _id: resource_id
76
76
 
77
- @owner.observed[association_name] = associated
77
+ # Nullify associated object, so next time user accesses it,
78
+ # association loader loads the new object
79
+ @owner.observed[association_name] = null
78
80
 
79
81
  resource_id
80
82
 
@@ -83,7 +85,7 @@ subscribers =
83
85
  @owner.observed["#{@resource.toString()}_id"] = if associated then associated._id else null
84
86
 
85
87
  modifiers =
86
- # Called before record initialization to create the a lazy loader
88
+ # Called before record initialization to create the a lazy loader
87
89
  # for other records
88
90
  belongs_to:
89
91
  associated_loader: ->
@@ -102,7 +104,7 @@ modifiers =
102
104
  # resource and on retrievability of the resource
103
105
  return associated unless associated?._id? or associated_id
104
106
 
105
- # Retunrs imediatelly for resources on storage
107
+ # Returns imediatelly for resources on storage
106
108
  # TODO make this extenxible
107
109
  return associated if associated?.sustained
108
110
 
@@ -111,12 +113,17 @@ modifiers =
111
113
  console.warn "subscribers.belongs_to.foreign_key: associated factory not found for model: #{association_name}"
112
114
  return associated
113
115
 
116
+ # Search through stored resources to see if it is stored
114
117
  associated = resource.find associated_id || associated._id
115
- associated ||= resource _id: associated_id
116
118
 
117
- resource.storage.store associated._id, associated
118
- associated.reload()
119
+ # Found associated in storage, update this model and return associated
120
+ return @owner.observed[association_name] = associated if associated
121
+
122
+ # Not found associated in storage
123
+ associated ||= resource _id: associated_id # initialize and store a new record
124
+ associated.reload() # fetch resource
119
125
 
126
+ # Store temporary unloaded resource in this model
120
127
  @owner.observed[association_name] = associated
121
128
 
122
129
  configurable: true
@@ -133,9 +140,14 @@ callbacks =
133
140
  association_names = model[@resource].has_many
134
141
  if association_names
135
142
  for association_name in association_names
143
+
144
+ # Instantiate new records for the association attributes
145
+ # TODO DO not support '_attributes' property on instantiating!
146
+ # TODO define setter for attributes
136
147
  associations_attributes = @["#{association_name}_attributes"]
148
+ association = @[model.pluralize association_name]
149
+
137
150
  if associations_attributes and associations_attributes.length
138
- association = @[model.pluralize association_name]
139
151
 
140
152
  unless association
141
153
  message = "has_many.nest_attributes: Association not found for #{association_name}. \n"
@@ -232,9 +244,19 @@ associable =
232
244
  # @resource = model[resource].resource
233
245
 
234
246
  # TODO Remember to clear association proxy when object is destroyed
235
- association_proxy = resource: resource, parent_resource: @resource, parent: @
236
- association_name = model.pluralize resource
237
- @[association_name] = $.extend association_proxy, plural
247
+ association_proxy = resource: resource, parent_resource: @resource, parent: @
248
+ association_name = model.pluralize resource
249
+
250
+ # When deserializing has many associated resources from
251
+ # server, it is common to send as the association without
252
+ # suffix
253
+ association_attributes = @[association_name] || []
254
+ @["#{association_name}_attributes"] ||= []
255
+ @["#{association_name}_attributes"] = @["#{association_name}_attributes"].concat association_attributes if association_attributes.length
256
+
257
+ # Create or Override sent attributes by the association proxy
258
+ @[association_name] = $.extend association_proxy, plural
259
+
238
260
 
239
261
  # Update association attribute
240
262
  @after 'saved', callbacks.has_many.update_association
@@ -273,7 +295,7 @@ associable =
273
295
  # TODO see why this code is here, since we have the owner key
274
296
  association_proxy[@resource.toString()] = @
275
297
 
276
- @["build_#{resource}" ] = $.proxy singular.build , association_proxy
298
+ @["build_#{resource}"] = $.proxy singular.build , association_proxy
277
299
  @["create_#{resource}"] = $.proxy singular.create, association_proxy
278
300
 
279
301
  # TODO copy from active record and better modularization of
@@ -281,19 +303,21 @@ associable =
281
303
  # To prevent association loading request we must nullify the
282
304
  # association when subscribing
283
305
  old_resource_id = @["#{resource}_id"]
306
+ old_dirty = @dirty
284
307
  @["#{resource}_id"] = null
285
308
 
286
309
  @subscribe "#{resource}_id" , $.proxy subscribers.belongs_to.foreign_key, association_proxy
287
310
  @subscribe resource.toString(), $.proxy subscribers.belongs_to.associated_changed, association_proxy
288
311
 
289
312
  # Restore id after loader prevention has passed
290
- @resource_id = old_resource_id
313
+ @["#{resource}_id"] = old_resource_id
314
+ @dirty = old_dirty
291
315
 
292
316
  # Execute relation attributes binding
293
317
  # TODO validate bindings! When @resource._id != @["#{resource}_id"]
294
318
  # TODO write test for this case
295
- if @["#{resource}_id"] and not @[resource]
296
- @publish "#{resource}_id", @["#{resource}_id"]
319
+ # if @["#{resource}_id"] and not @[resource]
320
+ # @publish "#{resource}_id", @["#{resource}_id"]
297
321
 
298
322
  # TODO better organization of this code, probably transforming the
299
323
  # association into a composable object inside this function: @ =
@@ -13,8 +13,13 @@ handlers =
13
13
  persistable =
14
14
  record:
15
15
  after_initialize: ->
16
- # TODO check persistable configuration before attaching handlers
17
- @after 'saved', handlers.store_after_saved
16
+ if @_id
17
+ # TODO remove global model usage
18
+ {storage} = model[@resource.toString()]
19
+ storage.store @_id, @
20
+ else
21
+ # TODO check persistable configuration before attaching handlers
22
+ @after 'saved', handlers.store_after_saved
18
23
 
19
24
  # Extend indemma
20
25
  # TODO use stampit to extend record and model
@@ -7,6 +7,7 @@ queryable =
7
7
  # FIXME don't let everyone use the same storage instance! or let it?
8
8
  storage: storable()
9
9
  find: (key) ->
10
+ throw new TypeError "InvalidFind: resource.find was called with a falsey value" unless key
10
11
  @storage.store key
11
12
  all: ->
12
13
  @storage.values()
@@ -24,6 +24,32 @@ resource = stampit
24
24
 
25
25
  @
26
26
 
27
+ # TODO Think of a better name, and move to a composable stampit item
28
+ descriptors =
29
+ route:
30
+ get: ->
31
+ # TODO use resource object on associations!
32
+ @resource = name: @resource if typeof @resource == 'string'
33
+
34
+ route = '/'
35
+ route += "#{@parent.route}/#{@parent._id}/" if @parent?
36
+ route += @resource.scope + '/' if @resource.scope?
37
+
38
+ route += if @resource.singular then @resource.name else model.pluralize @resource.name
39
+
40
+ @route = route
41
+
42
+ configurable: true
43
+ # set: (value) -> @initial_route = value
44
+
45
+ # TODO Deprecated! Remove on 15/02/2014
46
+ # parent_id:
47
+ # get: -> @[@parent_resource]._id if @[@parent_resource]
48
+ # set: -> console.error 'Warning changing associations throught parent_id not allowed for security and style guide purposes' # TODO
49
+ # configurable: true
50
+ # enumerable: true
51
+
52
+ # TODO Think of a better name, and move to a composable stampit item
27
53
  resourceable =
28
54
  pluralize: (word, count, plural) ->
29
55
  throw new TypeError "Invalid string passed to pluralize '#{word}'" unless word and word.length
@@ -41,36 +67,13 @@ resourceable =
41
67
  else
42
68
  word
43
69
 
44
- # TODO move to resourceable method
45
- route:
46
- get: ->
47
- return @initial_route if @initial_route?
48
-
49
- # TODO use resource object on associations!
50
- @resource = name: @resource if typeof @resource == 'string'
51
-
52
- route = '/'
53
- route += "#{@parent.route}/#{@parent._id}/" if @parent?
54
- route += @resource.scope + '/' if @resource.scope?
55
-
56
- route += if @resource.singular then @resource.name else model.pluralize @resource.name
57
- @initial_route = route
58
-
59
- route
60
-
61
- set: (value) -> @initial_route = value
62
-
63
- parent_id:
64
- get: -> @[@parent_resource]._id if @[@parent_resource]
65
- set: -> console.error 'Warning changing associations throught parent_id not allowed for security and style guide purposes' # TODO
66
-
67
70
  initialize: ->
71
+
72
+ # Deprecated! Remove on 15/02/2014
68
73
  # Set parent attribute and default nested route
69
- if @parent_resource
70
- Object.defineProperty @, "#{@parent_resource}_id",
71
- value: resourceable.parent_id
72
- configurable: true
73
- enumerable: true
74
+ # If you're using the associable plugin, this getter and setter will be overwritten!
75
+ # if @parent_resource
76
+ # Object.defineProperty @, "#{@parent_resource}_id", descriptors.parent_id
74
77
 
75
78
  # Setup resource
76
79
  resource_definition = {}
@@ -86,13 +89,10 @@ resourceable =
86
89
  # TODO remove mentions of @parent_resource and use only resource: {parent: ...}
87
90
  resource_definition.parent = @parent_resource
88
91
 
89
-
90
-
91
-
92
92
  @resource = resource resource_definition
93
93
 
94
94
  # TODO Support route parsing, and change route to /parents/:id/childrens
95
- @route ? Object.defineProperty @, 'route', resourceable.route
95
+ @route ? Object.defineProperty @, 'route', descriptors.route
96
96
 
97
97
 
98
98
  # Extend indemma