ende 0.2.9 → 0.2.10

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/javascripts/aura/extensions/devise.js.coffee +2 -2
  3. data/lib/assets/javascripts/widgets/viewer/main.js.coffee +1 -1
  4. data/lib/ende/version.rb +1 -1
  5. data/vendor/assets/components/build.js +638 -133
  6. data/vendor/components/indefinido-indemma/.gitignore +14 -0
  7. data/vendor/components/indefinido-indemma/.gitignore~ +2 -0
  8. data/vendor/components/indefinido-indemma/.ruby-gemset +1 -0
  9. data/vendor/components/indefinido-indemma/.ruby-version +1 -0
  10. data/vendor/components/indefinido-indemma/Gemfile +13 -0
  11. data/vendor/components/indefinido-indemma/Guardfile +39 -0
  12. data/vendor/components/indefinido-indemma/History.md +0 -0
  13. data/vendor/components/indefinido-indemma/Readme.md +447 -0
  14. data/vendor/components/indefinido-indemma/build/development.js +340 -0
  15. data/vendor/components/indefinido-indemma/build/release.js +22039 -0
  16. data/vendor/components/indefinido-indemma/build/test.js +22039 -0
  17. data/vendor/components/indefinido-indemma/component.json +7 -3
  18. data/vendor/components/indefinido-indemma/components/chaijs-assertion-error/component.json +18 -0
  19. data/vendor/components/indefinido-indemma/components/chaijs-assertion-error/index.js +110 -0
  20. data/vendor/components/indefinido-indemma/components/chaijs-chai/component.json +47 -0
  21. data/vendor/components/indefinido-indemma/components/chaijs-chai/index.js +1 -0
  22. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/assertion.js +130 -0
  23. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/core/assertions.js +1270 -0
  24. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/interface/assert.js +1080 -0
  25. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/interface/expect.js +12 -0
  26. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/interface/should.js +76 -0
  27. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/addChainableMethod.js +94 -0
  28. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/addMethod.js +37 -0
  29. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/addProperty.js +40 -0
  30. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/eql.js +129 -0
  31. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/flag.js +32 -0
  32. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getActual.js +19 -0
  33. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getEnumerableProperties.js +25 -0
  34. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getMessage.js +49 -0
  35. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getName.js +20 -0
  36. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getPathValue.js +102 -0
  37. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/getProperties.js +35 -0
  38. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/index.js +108 -0
  39. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/inspect.js +320 -0
  40. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/objDisplay.js +48 -0
  41. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/overwriteMethod.js +51 -0
  42. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/overwriteProperty.js +54 -0
  43. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/test.js +26 -0
  44. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/transferFlags.js +44 -0
  45. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai/utils/type.js +45 -0
  46. data/vendor/components/indefinido-indemma/components/chaijs-chai/lib/chai.js +80 -0
  47. data/vendor/components/indefinido-indemma/components/component-bind/component.json +14 -0
  48. data/vendor/components/indefinido-indemma/components/component-bind/index.js +24 -0
  49. data/vendor/components/indefinido-indemma/components/component-jquery/component.json +14 -0
  50. data/vendor/components/indefinido-indemma/components/component-jquery/index.js +9601 -0
  51. data/vendor/components/indefinido-indemma/components/component-type/component.json +18 -0
  52. data/vendor/components/indefinido-indemma/components/component-type/index.js +32 -0
  53. data/vendor/components/indefinido-indemma/components/indefinido-advisable/component.json +21 -0
  54. data/vendor/components/indefinido-indemma/components/indefinido-advisable/index.js +1 -0
  55. data/vendor/components/indefinido-indemma/components/indefinido-advisable/lib/advisable.js +60 -0
  56. data/vendor/components/indefinido-indemma/components/indefinido-observable/component.json +25 -0
  57. data/vendor/components/indefinido-indemma/components/indefinido-observable/components/cjohansen-sinon/sinon.js +4290 -0
  58. data/vendor/components/indefinido-indemma/components/indefinido-observable/index.js +1 -0
  59. data/vendor/components/indefinido-indemma/components/indefinido-observable/lib/adapters/rivets.js +26 -0
  60. data/vendor/components/indefinido-indemma/components/indefinido-observable/lib/observable.js +323 -0
  61. data/vendor/components/indefinido-indemma/components/indefinido-observable/vendor/shims/accessors-legacy.js +92 -0
  62. data/vendor/components/indefinido-indemma/components/indefinido-observable/vendor/shims/accessors.js +173 -0
  63. data/vendor/components/indefinido-indemma/components/indefinido-observable/vendor/shims/array.indexOf.js +8 -0
  64. data/vendor/components/indefinido-indemma/components/indefinido-observable/vendor/shims/object.create.js +77 -0
  65. data/vendor/components/indefinido-indemma/components/kapit-observe-utils/component.json +13 -0
  66. data/vendor/components/indefinido-indemma/components/paulmillr-es6-shim/component.json +17 -0
  67. data/vendor/components/indefinido-indemma/components/paulmillr-es6-shim/es6-shim.js +996 -0
  68. data/vendor/components/indefinido-indemma/components/pluma-assimilate/component.json +25 -0
  69. data/vendor/components/indefinido-indemma/components/pluma-assimilate/dist/assimilate.js +127 -0
  70. data/vendor/components/indefinido-indemma/karma.conf.js +86 -0
  71. data/vendor/components/indefinido-indemma/lib/record/associable.js +229 -82
  72. data/vendor/components/indefinido-indemma/lib/record/errors.js +1 -0
  73. data/vendor/components/indefinido-indemma/lib/record/persistable.js +32 -0
  74. data/vendor/components/indefinido-indemma/lib/record/queryable.js +32 -0
  75. data/vendor/components/indefinido-indemma/lib/record/resource.js +12 -4
  76. data/vendor/components/indefinido-indemma/lib/record/rest.js +1 -1
  77. data/vendor/components/indefinido-indemma/lib/record/restfulable.js +38 -27
  78. data/vendor/components/indefinido-indemma/lib/record/scopable.js +15 -2
  79. data/vendor/components/indefinido-indemma/lib/record/storable.js +48 -0
  80. data/vendor/components/indefinido-indemma/lib/record/validatable.js +10 -5
  81. data/vendor/components/indefinido-indemma/lib/record/validations/cpf.js +1 -1
  82. data/vendor/components/indefinido-indemma/lib/record.js +15 -12
  83. data/vendor/components/indefinido-indemma/spec/record/associable_spec.js +137 -0
  84. data/vendor/components/indefinido-indemma/spec/record/persistable_spec.js +36 -0
  85. data/vendor/components/indefinido-indemma/spec/record/queryable_spec.js +33 -0
  86. data/vendor/components/indefinido-indemma/spec/record/resource_spec.js +93 -0
  87. data/vendor/components/indefinido-indemma/spec/record/rest_spec.js +32 -0
  88. data/vendor/components/indefinido-indemma/spec/record/restfulable_spec.js +288 -0
  89. data/vendor/components/indefinido-indemma/spec/record/scopable_spec.js +212 -0
  90. data/vendor/components/indefinido-indemma/spec/record/storable_spec.js +53 -0
  91. data/vendor/components/indefinido-indemma/spec/record/translationable.js +28 -0
  92. data/vendor/components/indefinido-indemma/spec/record/validatable_spec.js +111 -0
  93. data/vendor/components/indefinido-indemma/spec/record/validations/associated_spec.js +43 -0
  94. data/vendor/components/indefinido-indemma/spec/record/validations/confirmation_spec.js +36 -0
  95. data/vendor/components/indefinido-indemma/spec/record/validations/cpf_spec.js +35 -0
  96. data/vendor/components/indefinido-indemma/spec/record/validations/presence_spec.js +28 -0
  97. data/vendor/components/indefinido-indemma/spec/record/validations/remote_spec.js +87 -0
  98. data/vendor/components/indefinido-indemma/spec/record/validations/type_spec.js +48 -0
  99. data/vendor/components/indefinido-indemma/spec/record_spec.js +37 -0
  100. data/vendor/components/indefinido-indemma/spec/spec_helper.js +11 -0
  101. data/vendor/components/indefinido-indemma/spec/support/value_objects/phone.js +45 -0
  102. data/vendor/components/indefinido-indemma/src/lib/extensions/rivets.coffee +17 -0
  103. data/vendor/components/indefinido-indemma/src/lib/record/associable.coffee +342 -0
  104. data/vendor/components/indefinido-indemma/src/lib/record/errors.coffee +20 -0
  105. data/vendor/components/indefinido-indemma/src/lib/record/maid.coffee +16 -0
  106. data/vendor/components/indefinido-indemma/src/lib/record/persistable.coffee +27 -0
  107. data/vendor/components/indefinido-indemma/src/lib/record/queryable.coffee +29 -0
  108. data/vendor/components/indefinido-indemma/src/lib/record/resource.coffee +106 -0
  109. data/vendor/components/indefinido-indemma/src/lib/record/rest.coffee +28 -0
  110. data/vendor/components/indefinido-indemma/src/lib/record/restfulable.coffee +348 -0
  111. data/vendor/components/indefinido-indemma/src/lib/record/scopable.coffee +275 -0
  112. data/vendor/components/indefinido-indemma/src/lib/record/storable.coffee +46 -0
  113. data/vendor/components/indefinido-indemma/src/lib/record/translationable.coffee +18 -0
  114. data/vendor/components/indefinido-indemma/src/lib/record/validatable.coffee +217 -0
  115. data/vendor/components/indefinido-indemma/src/lib/record/validations/associated.coffee +32 -0
  116. data/vendor/components/indefinido-indemma/src/lib/record/validations/confirmation.coffee +19 -0
  117. data/vendor/components/indefinido-indemma/src/lib/record/validations/cpf.coffee +58 -0
  118. data/vendor/components/indefinido-indemma/src/lib/record/validations/presence.coffee +19 -0
  119. data/vendor/components/indefinido-indemma/src/lib/record/validations/remote.coffee +65 -0
  120. data/vendor/components/indefinido-indemma/src/lib/record/validations/type.coffee +32 -0
  121. data/vendor/components/indefinido-indemma/src/lib/record.coffee +136 -0
  122. data/vendor/components/indefinido-indemma/src/spec/record/associable_spec.coffee +130 -0
  123. data/vendor/components/indefinido-indemma/src/spec/record/persistable_spec.coffee +30 -0
  124. data/vendor/components/indefinido-indemma/src/spec/record/queryable_spec.coffee +27 -0
  125. data/vendor/components/indefinido-indemma/src/spec/record/resource_spec.coffee +69 -0
  126. data/vendor/components/indefinido-indemma/src/spec/record/rest_spec.coffee +22 -0
  127. data/vendor/components/indefinido-indemma/src/spec/record/restfulable_spec.coffee +207 -0
  128. data/vendor/components/indefinido-indemma/src/spec/record/scopable_spec.coffee +191 -0
  129. data/vendor/components/indefinido-indemma/src/spec/record/storable_spec.coffee +40 -0
  130. data/vendor/components/indefinido-indemma/src/spec/record/translationable.coffee +19 -0
  131. data/vendor/components/indefinido-indemma/src/spec/record/validatable_spec.coffee +100 -0
  132. data/vendor/components/indefinido-indemma/src/spec/record/validations/associated_spec.coffee +35 -0
  133. data/vendor/components/indefinido-indemma/src/spec/record/validations/confirmation_spec.coffee +25 -0
  134. data/vendor/components/indefinido-indemma/src/spec/record/validations/cpf_spec.coffee +28 -0
  135. data/vendor/components/indefinido-indemma/src/spec/record/validations/presence_spec.coffee +24 -0
  136. data/vendor/components/indefinido-indemma/src/spec/record/validations/remote_spec.coffee +74 -0
  137. data/vendor/components/indefinido-indemma/src/spec/record/validations/type_spec.coffee +33 -0
  138. data/vendor/components/indefinido-indemma/src/spec/record_spec.coffee +23 -0
  139. data/vendor/components/indefinido-indemma/src/spec/spec_helper.coffee +9 -0
  140. data/vendor/components/indefinido-indemma/src/spec/support/value_objects/phone.coffee +30 -0
  141. data/vendor/components/indefinido-indemma/vendor/object/mixin.js +196 -0
  142. data/vendor/components/indefinido-indemma/vendor/owl/pluralize.js +190 -0
  143. metadata +130 -2
@@ -0,0 +1,342 @@
1
+ root = window
2
+ $ = require 'jquery'
3
+ extend = require 'assimilate'
4
+
5
+ require './resource'
6
+
7
+ # Store association methods
8
+ # TODO Implement setter for route
9
+ plural = # has_many ## TODO embeds_many
10
+ add : (params...) ->
11
+ # TODO check for id and instantly add resource
12
+ # TODO Set foreign keys?
13
+ @push @build attributes for attributes in params
14
+
15
+ create: (params...) ->
16
+ for attributes in params
17
+ record = @build attributes
18
+ @push record
19
+ record.save()
20
+ build: (data = {}) ->
21
+ data.parent_resource = @parent_resource
22
+
23
+
24
+ # TODO Setup a before save callback to generate route when there is no id
25
+ data.route ||= "#{@parent.route}/#{@parent._id}/#{model.pluralize @resource.toString()}" if @parent?
26
+ throw "associable.has_many: cannot redefine route of association #{@parent_resource}.#{@resource} from #{@route} to #{data.route}" if @route isnt data.route and @route
27
+ # Adds parent record to children side of association, if not set
28
+ # TODO check if this reference is unmade on instance elimination
29
+ data[@parent_resource] ||= @parent
30
+
31
+ # TODO store a singular copy of the resource for better performace
32
+ model[model.singularize @resource] data
33
+ push : ->
34
+ console.warn "#{@resource}.push is deprecated and will be removed, please use add instead"
35
+ Array.prototype.push.apply @, arguments
36
+
37
+ length : 0
38
+ json : (methods, omissions) -> record.json(methods, omissions) for record in @
39
+
40
+
41
+ singular = # belongs_to, has_one ## TODO embeds_one, embedded_in
42
+ # @ = record
43
+ create: (data) -> model[@resource].create extend {}, @, data
44
+ # @ = record
45
+ # TODO convert to association proxy
46
+ build : (data) ->
47
+ # Adds child record of association to parent, and returns new
48
+ # record
49
+ @owner[@resource.toString()] = model[@resource.toString()] extend {}, @, data
50
+
51
+ subscribers =
52
+ belongs_to:
53
+ foreign_key: (resource_id) ->
54
+ association_name = @resource.toString()
55
+
56
+ # TODO faster nullifing association check
57
+ # TODO only allow nullifying with null
58
+ if resource_id == null or resource_id == undefined
59
+ @dirty = true
60
+ @owner[association_name] = resource_id
61
+ return resource_id
62
+
63
+ # TODO Discover and update inverse side of association
64
+ # associated[@owner.resource.toString()] = @owner
65
+ current_resource_id = @owner[association_name]?._id
66
+ if resource_id != current_resource_id
67
+ # Update association with blank resource that will update
68
+ resource = model[association_name]
69
+ unless resource
70
+ console.warn "subscribers.belongs_to.foreign_key: associated factory not found for model: #{association_name}"
71
+ return resource_id
72
+
73
+ # 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
76
+
77
+ @owner.observed[association_name] = associated
78
+
79
+ resource_id
80
+
81
+ # Called when associated record changes, so we can silently update the id
82
+ associated_changed: (associated) ->
83
+ @owner.observed["#{@resource.toString()}_id"] = if associated then associated._id else null
84
+
85
+ modifiers =
86
+ # Called before record initialization to create the a lazy loader
87
+ # for other records
88
+ belongs_to:
89
+ associated_loader: ->
90
+ association_name = @resource.toString()
91
+
92
+ Object.defineProperty @owner, association_name,
93
+ # Observable already sets property for us
94
+ set: (associated) ->
95
+ @observed[association_name] = associated
96
+
97
+ get: =>
98
+ associated = @owner.observed[association_name]
99
+ associated_id = @owner.observed[association_name + '_id']
100
+
101
+ # Returns null or undefined depending on sustained state of
102
+ # resource and on retrievability of the resource
103
+ return associated unless associated?._id? or associated_id
104
+
105
+ # Retunrs imediatelly for resources on storage
106
+ # TODO make this extenxible
107
+ return associated if associated?.sustained
108
+
109
+ resource = model[association_name]
110
+ unless resource
111
+ console.warn "subscribers.belongs_to.foreign_key: associated factory not found for model: #{association_name}"
112
+ return associated
113
+
114
+ associated = resource.find associated_id || associated._id
115
+ associated ||= resource _id: associated_id
116
+
117
+ resource.storage.store associated._id, associated
118
+ associated.reload()
119
+
120
+ @owner.observed[association_name] = associated
121
+
122
+ configurable: true
123
+ enumerable: true
124
+
125
+ callbacks =
126
+ has_many:
127
+ # Forward association nested attributes
128
+ # TODO write attribute setter, and remove this code
129
+ nest_attributes: ->
130
+ # TODO only nest specified nested attributes on model definition
131
+ # TODO remove associations iteration, and pass throught parameter
132
+ # TODO DO not support '_attributes' property on instantiating!
133
+ association_names = model[@resource].has_many
134
+ if association_names
135
+ for association_name in association_names
136
+ associations_attributes = @["#{association_name}_attributes"]
137
+ if associations_attributes and associations_attributes.length
138
+ association = @[model.pluralize association_name]
139
+
140
+ unless association
141
+ message = "has_many.nest_attributes: Association not found for #{association_name}. \n"
142
+ message += "did you set it on model declaration? \n has_many: #{association_name} "
143
+ throw message
144
+
145
+ # TODO store a singular copy of the resource for better performace
146
+ association.resource = model.singularize association.resource
147
+ association.add.apply association, associations_attributes
148
+ association.resource = model.pluralize association.resource
149
+
150
+ # TODO Update route after setting the id
151
+ # TODO Update route association only once for each associated record
152
+ update_association: (data) ->
153
+ id = @_id || data && (data._id || data.id)
154
+
155
+ # Keep trying until we have a id
156
+ return unless id
157
+
158
+ for association_name in model[@resource.toString()].has_many
159
+ pluralized_association = model.pluralize association_name
160
+ association = @[pluralized_association]
161
+ # TODO setter of association.route
162
+ # to automatically update associated records
163
+ unless association.route
164
+ association.route = "/#{model.pluralize @resource.toString()}/#{id}/#{model.pluralize association.resource}"
165
+
166
+ for associated in association when not associated.route and associated.parent?
167
+ associated.route = "/#{model.pluralize @resource.toString()}/#{id}/#{model.pluralize association.resource}"
168
+
169
+ true
170
+ autosave: ->
171
+ throw 'Not implemented yet'
172
+ # @save()
173
+
174
+ has_one:
175
+ # Forward association nested attributes
176
+ # TODO write attribute setter, and remove this code
177
+ nest_attributes: ->
178
+ # TODO only nest specified nested attributes on model definition
179
+ # TODO convert to associations instead of association name
180
+ # TODO remove associations iteration, and pass throught parameter
181
+ # TODO DO not support '_attributes' property on instantiating!
182
+ association_names = model[@resource].has_one
183
+ if association_names
184
+ for association_name in association_names
185
+ associations_attributes = @["#{association_name}_attributes"]
186
+ if associations_attributes
187
+ @[association_name] = @["build_#{association_name}"] associations_attributes
188
+ delete @["#{association_name}_attributes"]
189
+
190
+
191
+ # TODO Better association segregation
192
+ associable =
193
+ model:
194
+
195
+ # @ = model instance
196
+ # param definition modable
197
+ blender: (definition) ->
198
+ {model} = associable
199
+
200
+ @create_after_hooks = model.create_after_hooks
201
+ @create_before_hooks = model.create_before_hooks
202
+
203
+ # TODO better default definition of associations
204
+ @has_many = [@has_many ] if @has_many and $.type(@has_many) != 'array'
205
+ @has_one = [@has_one ] if @has_one and $.type(@has_one) != 'array'
206
+ @belongs_to = [@belongs_to] if @belongs_to and $.type(@belongs_to) != 'array'
207
+
208
+ @has_many ||= []
209
+ @has_one ||= []
210
+ @belongs_to ||= []
211
+
212
+ true
213
+
214
+
215
+ # TODO better organisation of this code
216
+ # inside this function: @ = record (running on after_initialize)
217
+ create_after_hooks: (definition) ->
218
+
219
+ # TODO Rename options to definition
220
+ options = model[@resource.name || @resource.toString()]
221
+
222
+ # Create association methods
223
+ # Setup one to many association in model
224
+ if options.has_many
225
+
226
+ # TODO accept more options on has_many association creation
227
+ for resource in options.has_many
228
+ # unless model[resource]
229
+ # throw "Model not found for association with resource '#{resource}', on association 'has_many' "
230
+
231
+ # TODO instantiate default resources in has_many association
232
+ # @resource = model[resource].resource
233
+
234
+ # 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
238
+
239
+ # Update association attribute
240
+ @after 'saved', callbacks.has_many.update_association
241
+
242
+ # Forward nested attributes
243
+ callbacks.has_many.nest_attributes.call @
244
+
245
+ if options.has_one
246
+ for resource in options.has_one
247
+ # unless model[resource]
248
+ # throw "Model not found for association with resource '#{resource}', on association 'has_one' "
249
+
250
+ # TODO deprecate parent_resource
251
+ association_proxy = resource: resource, parent_resource: @resource, owner: @
252
+ association_proxy[@resource.toString()] = @
253
+
254
+ @["build_#{resource}" ] = $.proxy singular.build , association_proxy
255
+ @["create_#{resource}"] = $.proxy singular.create, association_proxy
256
+
257
+ # Update association attribute
258
+ # TODO @after 'saved', callbacks.has_many.update_association
259
+
260
+ # Forward nested attributes
261
+ callbacks.has_one.nest_attributes.call @
262
+
263
+ # Externalize this to a file
264
+ if options.belongs_to
265
+ # TODO implement association reflection!
266
+ for resource in options.belongs_to
267
+ # unless model[resource]
268
+ # throw "Model not found for association with resource '#{resource}', on association 'belongs_to' "
269
+
270
+ # TODO put deprecation warning on parent key
271
+ association_proxy = resource: resource, parent_resource: @resource, parent: @, owner: @
272
+
273
+ # TODO see why this code is here, since we have the owner key
274
+ association_proxy[@resource.toString()] = @
275
+
276
+ @["build_#{resource}" ] = $.proxy singular.build , association_proxy
277
+ @["create_#{resource}"] = $.proxy singular.create, association_proxy
278
+
279
+ # TODO copy from active record and better modularization of
280
+ # this internals
281
+ # To prevent association loading request we must nullify the
282
+ # association when subscribing
283
+ old_resource_id = @["#{resource}_id"]
284
+ @["#{resource}_id"] = null
285
+
286
+ @subscribe "#{resource}_id" , $.proxy subscribers.belongs_to.foreign_key, association_proxy
287
+ @subscribe resource.toString(), $.proxy subscribers.belongs_to.associated_changed, association_proxy
288
+
289
+ # Restore id after loader prevention has passed
290
+ @resource_id = old_resource_id
291
+
292
+ # Execute relation attributes binding
293
+ # TODO validate bindings! When @resource._id != @["#{resource}_id"]
294
+ # TODO write test for this case
295
+ if @["#{resource}_id"] and not @[resource]
296
+ @publish "#{resource}_id", @["#{resource}_id"]
297
+
298
+ # TODO better organization of this code, probably transforming the
299
+ # association into a composable object inside this function: @ =
300
+ # record (running on before_initialize) Beware there is no
301
+ # advisable or observable features
302
+ # @ = model
303
+ # param record = record instance
304
+ create_before_hooks: (record) ->
305
+ definition = @
306
+
307
+ # TODO Externalize this to a file
308
+ if definition.belongs_to
309
+
310
+ # TODO implement association reflection!
311
+ for resource in definition.belongs_to
312
+ # unless model[resource]
313
+ # throw "Model not found for association with resource '#{resource}', on association 'belongs_to' "
314
+
315
+ # TODO put deprecation warning on parent key
316
+ association_proxy = resource: resource, parent_resource: @resource, owner: record
317
+
318
+ modifiers.belongs_to.associated_loader.call association_proxy
319
+
320
+
321
+ # @ = record
322
+ record:
323
+ after_initialize: (attributes) ->
324
+ throw new Error 'resource must be defined in order to associate' unless @resource?
325
+ model[@resource.name || @resource.toString()].create_after_hooks.call @
326
+
327
+ before_initialize: (creation) ->
328
+ throw new Error 'resource must be defined in order to associate' unless @resource
329
+ model[@resource.name || @resource.toString()].create_before_hooks creation
330
+
331
+
332
+ # Extend indemma
333
+ model = root.model # TODO better way to get parent
334
+ model.mix (modelable) ->
335
+ modelable.after_mix.push associable.model.blender
336
+ modelable.record.before_initialize.push associable.record.before_initialize
337
+ modelable.record.after_initialize.push associable.record.after_initialize
338
+
339
+ # This allows to extendind the associable mixin
340
+ model.associable =
341
+ mix : (blender) ->
342
+ blender singular, plural
@@ -0,0 +1,20 @@
1
+ # TODO externalize errorsable from validatable
2
+ # errorsable = stampit
3
+ # add: (attribute, message_key, options) ->
4
+ #
5
+ # @push [attribute, message_key, options]
6
+ # @messages[attribute_name] messages[message_key](attribute_name)
7
+ #
8
+ # clear: ->
9
+ # if @length
10
+ # @length = 0
11
+ # @messages = {}
12
+ #
13
+ # push: Array.prototype.push
14
+ # splice: Array.prototype.splice
15
+ # ,
16
+ # messages: {}
17
+ # length: 0
18
+ # , ->
19
+ # @messages = []
20
+ # @
@@ -0,0 +1,16 @@
1
+ maid =
2
+
3
+ model : ->
4
+ @record.after_initialize.push maid.record if @washing?
5
+
6
+ record: ->
7
+
8
+ @subscribe 'dirty', (dirty) ->
9
+ dirty && setTimeout =>
10
+ @save()
11
+ , 500
12
+
13
+ # Extend indemma
14
+ model = window.model
15
+ model.mix (modelable) ->
16
+ modelable.after_mix.unshift maid.model
@@ -0,0 +1,27 @@
1
+ require './queryable'
2
+
3
+ handlers =
4
+ store_after_saved: ->
5
+ # TODO remove global model usage
6
+ {storage} = model[@resource.toString()]
7
+
8
+ # TODO check persistable configuration before attaching handlers
9
+ # and remove the @_id presence check
10
+ storage.store @_id, @ if @_id
11
+
12
+
13
+ persistable =
14
+ record:
15
+ after_initialize: ->
16
+ # TODO check persistable configuration before attaching handlers
17
+ @after 'saved', handlers.store_after_saved
18
+
19
+ # Extend indemma
20
+ # TODO use stampit to extend record and model
21
+ model = window.model # TODO better way to get parent
22
+ record = window.record # TODO better way to get parent
23
+
24
+ model.persistable = true
25
+
26
+ model.mix (modelable) ->
27
+ modelable.record.after_initialize.push persistable.record.after_initialize
@@ -0,0 +1,29 @@
1
+ extend = require 'assimilate'
2
+ storable = require './storable'
3
+ # merge = extend.withStrategy 'deep'
4
+ stampit = require '../../vendor/stampit'
5
+
6
+ queryable =
7
+ # FIXME don't let everyone use the same storage instance! or let it?
8
+ storage: storable()
9
+ find: (key) ->
10
+ @storage.store key
11
+ all: ->
12
+ @storage.values()
13
+ where: ->
14
+ throw new Error 'queryable.where: Not implemented yet'
15
+
16
+ # Extend indemma
17
+ # TODO use stampit to extend record and model
18
+ model = window.model # TODO better way to get parent
19
+ record = window.record # TODO better way to get parent
20
+
21
+ # queryable = stampit.compose queryable, storable
22
+
23
+
24
+ model.queryable = true
25
+ module.exports = queryable
26
+
27
+ model.mix (modelable) ->
28
+ # TODO use stampit to extend record and model
29
+ extend modelable, queryable
@@ -0,0 +1,106 @@
1
+ stampit = require '../../vendor/stampit'
2
+ require '../../vendor/owl/pluralize'
3
+
4
+ # TODO Think of a better name
5
+ resource = stampit
6
+ toString: -> @name
7
+ # TODO move resourceable.route() to here
8
+ ,
9
+ name : 'unknown'
10
+ scope : null
11
+ singular: false
12
+ , ->
13
+
14
+ # TODO better integration with record.coffee, and stop storing
15
+ # original reference
16
+ if @original_reference
17
+ stampit.mixIn @original_reference, @
18
+ @original_reference.toString = @toString
19
+ @original_reference.param_name ||= @name
20
+
21
+ return @original_reference
22
+
23
+ @param_name ||= @name
24
+
25
+ @
26
+
27
+ resourceable =
28
+ pluralize: (word, count, plural) ->
29
+ throw new TypeError "Invalid string passed to pluralize '#{word}'" unless word and word.length
30
+
31
+ unless word.indexOf('s') == word.length - 1
32
+ owl.pluralize word, count, plural
33
+ else
34
+ word
35
+
36
+ singularize: (word) ->
37
+ throw new TypeError "Invalid string passed to singularize '#{word}'" unless word and word.length
38
+
39
+ if word.lastIndexOf('s') == word.length - 1
40
+ word.substring 0, word.length - 1
41
+ else
42
+ word
43
+
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
+ initialize: ->
68
+ # 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
+
75
+ # Setup resource
76
+ resource_definition = {}
77
+ resource_definition = name: @resource if typeof @resource == 'string'
78
+ if typeof @resource == 'object'
79
+ # TODO deeper resource integration with record.coffee, and remove original reference
80
+ # To prevent reference lost and allow dinamic modification of resources
81
+ # we need to preserve the original reference
82
+ @resource.original_reference = @resource
83
+
84
+ resource_definition = @resource
85
+
86
+ # TODO remove mentions of @parent_resource and use only resource: {parent: ...}
87
+ resource_definition.parent = @parent_resource
88
+
89
+
90
+
91
+
92
+ @resource = resource resource_definition
93
+
94
+ # TODO Support route parsing, and change route to /parents/:id/childrens
95
+ @route ? Object.defineProperty @, 'route', resourceable.route
96
+
97
+
98
+ # Extend indemma
99
+ model = window.model # TODO better way to get parent
100
+
101
+ model.mix (modelable) ->
102
+ modelable.record.after_initialize.unshift resourceable.initialize
103
+ modelable.after_mix.unshift resourceable.initialize
104
+
105
+ model.singularize = resourceable.singularize
106
+ model.pluralize = resourceable.pluralize
@@ -0,0 +1,28 @@
1
+ $ = require 'jquery'
2
+
3
+ module.exports =
4
+ # TODO render route in the object itself with getter, and normalize this methods
5
+ get : (data) -> request.call @, 'get' , (if @_id then "#{@route}/#{@_id}" else @route), data
6
+ put : (data) -> request.call @, 'put' , (if @_id then "#{@route}/#{@_id}" else @route), data # TODO change from put to patch
7
+ post : (data) -> request.call @, 'post' , @route, data
8
+ delete: (data) -> request.call @, 'delete', (if @_id then "#{@route}/#{@_id}" else @route), data
9
+
10
+ request = (method, url, data) ->
11
+ param_name = @resource.param_name || @resource.toString()
12
+
13
+ # TODO optmize this serialization lookup
14
+ if not data and @json
15
+ data = {}
16
+ data[param_name] = @json()
17
+
18
+ if data and data[param_name]
19
+ delete data[param_name]['id']
20
+ delete data[param_name]['_id']
21
+
22
+
23
+ $.ajax
24
+ url : url
25
+ data : data
26
+ type : method
27
+ dataType: 'json'
28
+ context : @