ende 0.3.13 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/component.json +7 -0
- data/lib/assets/javascripts/aura/extensions/devise.js.coffee +2 -2
- data/lib/assets/javascripts/aura/extensions/loader.js.coffee +13 -11
- data/lib/assets/javascripts/aura/extensions/mask.js.coffee +54 -40
- data/lib/assets/javascripts/aura/extensions/mediator.js +5 -3
- data/lib/assets/javascripts/aura/extensions/models.js.coffee.erb +2 -2
- data/lib/assets/javascripts/aura/extensions/rivets/accounting.js.coffee +7 -1
- data/lib/assets/javascripts/aura/extensions/rivets/formatters.js.coffee +5 -1
- data/lib/assets/javascripts/aura/extensions/rivets.js.coffee +47 -29
- data/lib/assets/javascripts/aura/extensions/routes.js.coffee +10 -5
- data/lib/assets/javascripts/aura/extensions/states.js.coffee +2 -2
- data/lib/assets/javascripts/aura/extensions/widget/eventable.js.coffee +18 -19
- data/lib/assets/javascripts/aura/extensions/widget/lifecycleable.js.coffee +15 -10
- data/lib/assets/javascripts/config/initializers/jquery.js.coffee +2 -1
- data/lib/assets/javascripts/config/initializers/requirejs.js.coffee +3 -4
- data/lib/assets/javascripts/config/initializers.js.coffee +3 -0
- data/lib/assets/javascripts/config/load_components.js.coffee +106 -83
- data/lib/assets/javascripts/ende.js.coffee +13 -4
- data/lib/assets/javascripts/widgets/authenticator/presenter.js.coffee +3 -2
- data/lib/assets/javascripts/widgets/dialog/main.js.coffee +7 -3
- data/lib/assets/javascripts/widgets/support/main.js.coffee +3 -4
- data/lib/assets/javascripts/widgets/viewer/main.js.coffee +35 -103
- data/lib/assets/javascripts/widgets/viewer/presenters/default.js.coffee +2 -4
- data/lib/ende/version.rb +1 -1
- data/vendor/assets/components/build.js +30877 -0
- data/vendor/assets/components/ende_build.js +2487 -148
- data/vendor/assets/components/indemma_with_none.js +30553 -0
- data/vendor/assets/javascripts/spin/spin.js +349 -0
- data/vendor/components/indefinido-indemma/.gitignore +3 -0
- data/vendor/components/indefinido-indemma/.ruby-gemset +1 -1
- data/vendor/components/indefinido-indemma/.ruby-version +1 -1
- data/vendor/components/indefinido-indemma/build/development.js +17 -14
- data/vendor/components/indefinido-indemma/build/release.js +213 -148
- data/vendor/components/indefinido-indemma/build/test.js +213 -148
- data/vendor/components/indefinido-indemma/component.json +3 -1
- data/vendor/components/indefinido-indemma/karma.conf.js +50 -60
- data/vendor/components/indefinido-indemma/lib/record/associable.js +17 -17
- data/vendor/components/indefinido-indemma/lib/record/persistable.js +8 -1
- data/vendor/components/indefinido-indemma/lib/record/queryable.js +3 -0
- data/vendor/components/indefinido-indemma/lib/record/resource.js +25 -45
- data/vendor/components/indefinido-indemma/lib/record/restfulable.js +82 -28
- data/vendor/components/indefinido-indemma/lib/record/scopable.js +28 -2
- data/vendor/components/indefinido-indemma/lib/record/storable.js +1 -1
- data/vendor/components/indefinido-indemma/lib/record/validatable.js +15 -23
- data/vendor/components/indefinido-indemma/lib/record/validations/associated.js +3 -5
- data/vendor/components/indefinido-indemma/lib/record/validations/confirmation.js +3 -5
- data/vendor/components/indefinido-indemma/lib/record/validations/cpf.js +5 -7
- data/vendor/components/indefinido-indemma/lib/record/validations/presence.js +3 -5
- data/vendor/components/indefinido-indemma/lib/record/validations/remote.js +3 -7
- data/vendor/components/indefinido-indemma/lib/record/validations/type.js +2 -2
- data/vendor/components/indefinido-indemma/lib/record/validations/validatorable.js +12 -0
- data/vendor/components/indefinido-indemma/package.json +9 -0
- data/vendor/components/indefinido-indemma/spec/record/restfulable_spec.js +12 -0
- data/vendor/components/indefinido-indemma/spec/record/validatable_spec.js +4 -4
- data/vendor/components/indefinido-indemma/spec/record/validations/associated_spec.js +2 -2
- data/vendor/components/indefinido-indemma/src/lib/record/associable.coffee +44 -20
- data/vendor/components/indefinido-indemma/src/lib/record/persistable.coffee +7 -2
- data/vendor/components/indefinido-indemma/src/lib/record/queryable.coffee +1 -0
- data/vendor/components/indefinido-indemma/src/lib/record/resource.coffee +32 -32
- data/vendor/components/indefinido-indemma/src/lib/record/restfulable.coffee +79 -22
- data/vendor/components/indefinido-indemma/src/lib/record/scopable.coffee +27 -8
- data/vendor/components/indefinido-indemma/src/lib/record/storable.coffee +1 -1
- data/vendor/components/indefinido-indemma/src/lib/record/validatable.coffee +20 -19
- data/vendor/components/indefinido-indemma/src/lib/record/validations/associated.coffee +3 -5
- data/vendor/components/indefinido-indemma/src/lib/record/validations/confirmation.coffee +2 -4
- data/vendor/components/indefinido-indemma/src/lib/record/validations/cpf.coffee +4 -5
- data/vendor/components/indefinido-indemma/src/lib/record/validations/presence.coffee +2 -5
- data/vendor/components/indefinido-indemma/src/lib/record/validations/remote.coffee +3 -7
- data/vendor/components/indefinido-indemma/src/lib/record/validations/type.coffee +2 -3
- data/vendor/components/indefinido-indemma/src/lib/record/validations/validatorable.coffee +5 -0
- data/vendor/components/indefinido-indemma/src/spec/record/restfulable_spec.coffee +8 -0
- data/vendor/components/indefinido-indemma/src/spec/record/validatable_spec.coffee +4 -4
- data/vendor/components/indefinido-indemma/src/spec/record/validations/associated_spec.coffee +2 -2
- metadata +9 -3
- 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(
|
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() {
|
@@ -1,8 +1,8 @@
|
|
1
|
-
var errorsable, extensions, initializers, manager, messages, observable, root, stampit, type
|
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 :
|
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
|
-
|
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
|
-
|
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
|
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(
|
24
|
+
composed = stampit.compose(require('./validatorable'), associationable);
|
27
25
|
|
28
26
|
composed.definition_key = 'validates_associated';
|
29
27
|
|
30
|
-
|
28
|
+
module.exports = composed;
|
@@ -1,6 +1,4 @@
|
|
1
|
-
var composed, confirmationable, stampit
|
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(
|
13
|
+
composed = stampit.compose(require('./validatorable'), confirmationable);
|
16
14
|
|
17
15
|
composed.definition_key = 'validates_confirmation_of';
|
18
16
|
|
19
|
-
|
17
|
+
module.exports = composed;
|
@@ -1,6 +1,4 @@
|
|
1
|
-
var composed, cpfable, stampit
|
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 =
|
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 =
|
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(
|
54
|
+
composed = stampit.compose(require('./validatorable'), cpfable);
|
57
55
|
|
58
56
|
composed.definition_key = 'validates_cpf_format';
|
59
57
|
|
60
|
-
|
58
|
+
module.exports = composed;
|
@@ -1,6 +1,4 @@
|
|
1
|
-
var composed, presenceable, stampit
|
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(
|
13
|
+
composed = stampit.compose(require('./validatorable'), presenceable);
|
16
14
|
|
17
15
|
composed.definition_key = 'validates_presence_of';
|
18
16
|
|
19
|
-
|
17
|
+
module.exports = composed;
|
@@ -1,8 +1,4 @@
|
|
1
|
-
var composed, remoteable, rest,
|
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(
|
64
|
+
composed = stampit.compose(require('./validatorable'), remoteable);
|
69
65
|
|
70
66
|
composed.definition_key = 'validates_remotely';
|
71
67
|
|
72
|
-
|
68
|
+
module.exports = composed;
|
@@ -22,8 +22,8 @@ typeable = stampit({
|
|
22
22
|
}
|
23
23
|
});
|
24
24
|
|
25
|
-
composed = stampit.compose(
|
25
|
+
composed = stampit.compose(require('./validatorable'), typeable);
|
26
26
|
|
27
27
|
composed.definition_key = 'validates_type_of';
|
28
28
|
|
29
|
-
|
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
|
+
});
|
@@ -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('
|
21
|
+
return describe('(validates_... : ...)', function() {
|
22
22
|
describe('validators instatiation', function() {
|
23
|
-
it('should
|
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
|
35
|
+
return it('should have validators with in the key validates');
|
36
36
|
});
|
37
|
-
describe('
|
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
|
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('
|
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
|
58
|
-
|
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
|
75
|
-
associated
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
118
|
-
associated
|
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
|
236
|
-
association_name
|
237
|
-
|
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}"
|
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
|
-
@
|
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
|
-
|
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
|
-
|
17
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
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',
|
95
|
+
@route ? Object.defineProperty @, 'route', descriptors.route
|
96
96
|
|
97
97
|
|
98
98
|
# Extend indemma
|