ende 0.5.20 → 0.5.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/component.json +1 -1
  3. data/components/indefinido/indemma/master/.gitignore +17 -0
  4. data/components/indefinido/indemma/master/.ruby-gemset +1 -0
  5. data/components/indefinido/indemma/master/.ruby-version +1 -0
  6. data/components/indefinido/indemma/master/Gemfile +12 -0
  7. data/components/indefinido/indemma/master/Guardfile +39 -0
  8. data/components/indefinido/indemma/master/History.md +0 -0
  9. data/components/indefinido/indemma/master/Readme.md +445 -0
  10. data/components/indefinido/indemma/master/build/development.js +26123 -0
  11. data/components/indefinido/indemma/master/build/release.js +16741 -0
  12. data/components/indefinido/indemma/master/build/test.js +26123 -0
  13. data/components/indefinido/indemma/master/component.json +1 -1
  14. data/components/indefinido/indemma/master/components/chaijs/assertion-error/1.0.0/component.json +18 -0
  15. data/components/indefinido/indemma/master/components/chaijs/assertion-error/1.0.0/index.js +110 -0
  16. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.gitignore +22 -0
  17. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.mailmap +1 -0
  18. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.npmignore +14 -0
  19. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/.travis.yml +14 -0
  20. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/CONTRIBUTING.md +173 -0
  21. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/History.md +895 -0
  22. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/Makefile +93 -0
  23. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/README.md +99 -0
  24. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/ReleaseNotes.md +482 -0
  25. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/bower.json +27 -0
  26. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/chai.js +4782 -0
  27. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/component.json +50 -0
  28. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/index.js +1 -0
  29. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/karma.conf.js +28 -0
  30. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/karma.sauce.js +41 -0
  31. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/assertion.js +130 -0
  32. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/config.js +50 -0
  33. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/core/assertions.js +1314 -0
  34. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/assert.js +1056 -0
  35. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/expect.js +12 -0
  36. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/interface/should.js +78 -0
  37. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addChainableMethod.js +111 -0
  38. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addMethod.js +43 -0
  39. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/addProperty.js +40 -0
  40. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/flag.js +32 -0
  41. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getActual.js +18 -0
  42. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getEnumerableProperties.js +25 -0
  43. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getMessage.js +49 -0
  44. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getName.js +20 -0
  45. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getPathValue.js +102 -0
  46. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/getProperties.js +35 -0
  47. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/index.js +114 -0
  48. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/inspect.js +320 -0
  49. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/objDisplay.js +49 -0
  50. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteChainableMethod.js +53 -0
  51. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteMethod.js +51 -0
  52. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/overwriteProperty.js +54 -0
  53. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/test.js +26 -0
  54. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/transferFlags.js +44 -0
  55. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai/utils/type.js +45 -0
  56. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/lib/chai.js +87 -0
  57. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/package.json +42 -0
  58. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/sauce.browsers.js +128 -0
  59. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/support/sauce/sauce_connect_block.sh +7 -0
  60. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/support/sauce/sauce_connect_setup.sh +53 -0
  61. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/assert.js +638 -0
  62. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/auth/.gitkeep +0 -0
  63. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/bootstrap/index.js +22 -0
  64. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/bootstrap/karma.js +22 -0
  65. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/configuration.js +133 -0
  66. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/display/errors.js +14 -0
  67. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/display/message.js +47 -0
  68. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/expect.js +814 -0
  69. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/globalShould.js +15 -0
  70. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/plugins.js +24 -0
  71. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/should.js +744 -0
  72. data/components/indefinido/indemma/master/components/chaijs/chai/1.9.1/test/utilities.js +309 -0
  73. data/components/indefinido/indemma/master/components/chaijs/deep-eql/0.1.3/component.json +20 -0
  74. data/components/indefinido/indemma/master/components/chaijs/deep-eql/0.1.3/lib/eql.js +257 -0
  75. data/components/indefinido/indemma/master/components/chaijs/type-detect/0.1.1/component.json +18 -0
  76. data/components/indefinido/indemma/master/components/chaijs/type-detect/0.1.1/lib/type.js +142 -0
  77. data/components/indefinido/indemma/master/components/component/bind/1.0.0/component.json +14 -0
  78. data/components/indefinido/indemma/master/components/component/bind/1.0.0/index.js +23 -0
  79. data/components/indefinido/indemma/master/components/component/jquery/1.0.0/component.json +10 -0
  80. data/components/indefinido/indemma/master/components/component/jquery/1.0.0/index.js +10308 -0
  81. data/components/indefinido/indemma/master/components/component/type/1.0.0/component.json +20 -0
  82. data/components/indefinido/indemma/master/components/component/type/1.0.0/index.js +32 -0
  83. data/components/indefinido/indemma/master/components/indefinido/advisable/master/component.json +21 -0
  84. data/components/indefinido/indemma/master/components/indefinido/advisable/master/index.js +1 -0
  85. data/components/indefinido/indemma/master/components/indefinido/advisable/master/lib/advisable.js +60 -0
  86. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/component.json +39 -0
  87. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/index.js +1 -0
  88. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/adapters/rivets.js +40 -0
  89. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/legacy/notifierable.js +145 -0
  90. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/legacy/schedulerable.js +147 -0
  91. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/lookup.js +38 -0
  92. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/keypath_observer.js +38 -0
  93. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/observation.js +45 -0
  94. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/selection.js +57 -0
  95. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable/self_observer.js +38 -0
  96. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/observable.js +97 -0
  97. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/lib/platform.js +12 -0
  98. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/observe-js/observe.js +1631 -0
  99. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/accessors-legacy.js +92 -0
  100. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/accessors.js +248 -0
  101. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/array.indexOf.js +8 -0
  102. data/components/indefinido/indemma/master/components/indefinido/observable/es6-modules/vendor/shims/object.create.js +77 -0
  103. data/components/indefinido/indemma/master/components/pluma/assimilate/0.4.0/component.json +25 -0
  104. data/components/indefinido/indemma/master/components/pluma/assimilate/0.4.0/dist/assimilate.js +127 -0
  105. data/components/indefinido/indemma/master/karma.conf.js +75 -0
  106. data/components/indefinido/indemma/master/lib/record/associable.js +4 -2
  107. data/components/indefinido/indemma/master/lib/record/dirtyable.js +1 -1
  108. data/components/indefinido/indemma/master/package.json +9 -0
  109. data/components/indefinido/indemma/master/spec/record/associable_spec.js +211 -0
  110. data/components/indefinido/indemma/master/spec/record/dirtyable_spec.js +57 -0
  111. data/components/indefinido/indemma/master/spec/record/maid_spec.js +40 -0
  112. data/components/indefinido/indemma/master/spec/record/persistable_spec.js +46 -0
  113. data/components/indefinido/indemma/master/spec/record/queryable_spec.js +39 -0
  114. data/components/indefinido/indemma/master/spec/record/resource_spec.js +93 -0
  115. data/components/indefinido/indemma/master/spec/record/rest_spec.js +32 -0
  116. data/components/indefinido/indemma/master/spec/record/restfulable_spec.js +346 -0
  117. data/components/indefinido/indemma/master/spec/record/scopable_spec.js +242 -0
  118. data/components/indefinido/indemma/master/spec/record/storable_spec.js +44 -0
  119. data/components/indefinido/indemma/master/spec/record/translationable.js +28 -0
  120. data/components/indefinido/indemma/master/spec/record/validatable_spec.js +142 -0
  121. data/components/indefinido/indemma/master/spec/record/validations/associated_spec.js +43 -0
  122. data/components/indefinido/indemma/master/spec/record/validations/confirmation_spec.js +36 -0
  123. data/components/indefinido/indemma/master/spec/record/validations/cpf_spec.js +34 -0
  124. data/components/indefinido/indemma/master/spec/record/validations/presence_spec.js +28 -0
  125. data/components/indefinido/indemma/master/spec/record/validations/remote_spec.js +87 -0
  126. data/components/indefinido/indemma/master/spec/record/validations/type_spec.js +48 -0
  127. data/components/indefinido/indemma/master/spec/record_spec.js +49 -0
  128. data/components/indefinido/indemma/master/spec/spec_helper.js +15 -0
  129. data/components/indefinido/indemma/master/spec/support/value_objects/phone.js +45 -0
  130. data/components/indefinido/indemma/master/src/lib/extensions/rivets.coffee +17 -0
  131. data/components/indefinido/indemma/master/src/lib/record/associable.coffee +419 -0
  132. data/components/indefinido/indemma/master/src/lib/record/dirtyable.coffee +47 -0
  133. data/components/indefinido/indemma/master/src/lib/record/errors.coffee +20 -0
  134. data/components/indefinido/indemma/master/src/lib/record/maid.coffee +16 -0
  135. data/components/indefinido/indemma/master/src/lib/record/persistable.coffee +34 -0
  136. data/components/indefinido/indemma/master/src/lib/record/queryable.coffee +29 -0
  137. data/components/indefinido/indemma/master/src/lib/record/resource.coffee +107 -0
  138. data/components/indefinido/indemma/master/src/lib/record/rest.coffee +34 -0
  139. data/components/indefinido/indemma/master/src/lib/record/restfulable.coffee +487 -0
  140. data/components/indefinido/indemma/master/src/lib/record/scopable.coffee +279 -0
  141. data/components/indefinido/indemma/master/src/lib/record/storable.coffee +49 -0
  142. data/components/indefinido/indemma/master/src/lib/record/translationable.coffee +18 -0
  143. data/components/indefinido/indemma/master/src/lib/record/validatable.coffee +241 -0
  144. data/components/indefinido/indemma/master/src/lib/record/validations/associated.coffee +34 -0
  145. data/components/indefinido/indemma/master/src/lib/record/validations/confirmation.coffee +17 -0
  146. data/components/indefinido/indemma/master/src/lib/record/validations/cpf.coffee +57 -0
  147. data/components/indefinido/indemma/master/src/lib/record/validations/presence.coffee +16 -0
  148. data/components/indefinido/indemma/master/src/lib/record/validations/remote.coffee +61 -0
  149. data/components/indefinido/indemma/master/src/lib/record/validations/type.coffee +31 -0
  150. data/components/indefinido/indemma/master/src/lib/record/validations/validatorable.coffee +5 -0
  151. data/components/indefinido/indemma/master/src/lib/record.coffee +143 -0
  152. data/components/indefinido/indemma/master/src/spec/record/associable_spec.coffee +205 -0
  153. data/components/indefinido/indemma/master/src/spec/record/dirtyable_spec.coffee +47 -0
  154. data/components/indefinido/indemma/master/src/spec/record/maid_spec.coffee +34 -0
  155. data/components/indefinido/indemma/master/src/spec/record/persistable_spec.coffee +39 -0
  156. data/components/indefinido/indemma/master/src/spec/record/queryable_spec.coffee +33 -0
  157. data/components/indefinido/indemma/master/src/spec/record/resource_spec.coffee +69 -0
  158. data/components/indefinido/indemma/master/src/spec/record/rest_spec.coffee +22 -0
  159. data/components/indefinido/indemma/master/src/spec/record/restfulable_spec.coffee +257 -0
  160. data/components/indefinido/indemma/master/src/spec/record/scopable_spec.coffee +227 -0
  161. data/components/indefinido/indemma/master/src/spec/record/storable_spec.coffee +39 -0
  162. data/components/indefinido/indemma/master/src/spec/record/translationable.coffee +19 -0
  163. data/components/indefinido/indemma/master/src/spec/record/validatable_spec.coffee +127 -0
  164. data/components/indefinido/indemma/master/src/spec/record/validations/associated_spec.coffee +35 -0
  165. data/components/indefinido/indemma/master/src/spec/record/validations/confirmation_spec.coffee +25 -0
  166. data/components/indefinido/indemma/master/src/spec/record/validations/cpf_spec.coffee +27 -0
  167. data/components/indefinido/indemma/master/src/spec/record/validations/presence_spec.coffee +24 -0
  168. data/components/indefinido/indemma/master/src/spec/record/validations/remote_spec.coffee +74 -0
  169. data/components/indefinido/indemma/master/src/spec/record/validations/type_spec.coffee +33 -0
  170. data/components/indefinido/indemma/master/src/spec/record_spec.coffee +29 -0
  171. data/components/indefinido/indemma/master/src/spec/spec_helper.coffee +11 -0
  172. data/components/indefinido/indemma/master/src/spec/support/value_objects/phone.coffee +30 -0
  173. data/components/indefinido/indemma/master/vendor/object/mixin.js +196 -0
  174. data/components/indefinido/indemma/master/vendor/spec/sinon/assert.js +199 -0
  175. data/components/indefinido/indemma/master/vendor/spec/sinon/behavior.js +334 -0
  176. data/components/indefinido/indemma/master/vendor/spec/sinon/call.js +205 -0
  177. data/components/indefinido/indemma/master/vendor/spec/sinon/collection.js +155 -0
  178. data/components/indefinido/indemma/master/vendor/spec/sinon/match.js +245 -0
  179. data/components/indefinido/indemma/master/vendor/spec/sinon/mock.js +451 -0
  180. data/components/indefinido/indemma/master/vendor/spec/sinon/sandbox.js +144 -0
  181. data/components/indefinido/indemma/master/vendor/spec/sinon/spy.js +413 -0
  182. data/components/indefinido/indemma/master/vendor/spec/sinon/stub.js +161 -0
  183. data/components/indefinido/indemma/master/vendor/spec/sinon/test.js +77 -0
  184. data/components/indefinido/indemma/master/vendor/spec/sinon/test_case.js +99 -0
  185. data/components/indefinido/indemma/master/vendor/spec/sinon/util/event.js +94 -0
  186. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_server.js +212 -0
  187. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_server_with_clock.js +83 -0
  188. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_timers.js +405 -0
  189. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_xdomain_request.js +206 -0
  190. data/components/indefinido/indemma/master/vendor/spec/sinon/util/fake_xml_http_request.js +575 -0
  191. data/components/indefinido/indemma/master/vendor/spec/sinon/util/timers_ie.js +31 -0
  192. data/components/indefinido/indemma/master/vendor/spec/sinon/util/xdr_ie.js +14 -0
  193. data/components/indefinido/indemma/master/vendor/spec/sinon/util/xhr_ie.js +19 -0
  194. data/components/indefinido/indemma/master/vendor/spec/sinon.js +383 -0
  195. data/lib/assets/javascripts/value_objects/phone.js.coffee +3 -1
  196. data/lib/assets/javascripts/widgets/viewer/plugins/scopable.js.coffee +5 -5
  197. data/lib/ende/version.rb +1 -1
  198. data/vendor/assets/components/ende_build.css +4 -4
  199. data/vendor/assets/components/ende_build.js +7974 -7889
  200. metadata +191 -5
  201. data/vendor/assets/component/build.css +0 -112
  202. data/vendor/assets/components/build.css +0 -112
  203. data/vendor/assets/components/indemma_with_none.js +0 -30553
@@ -0,0 +1,419 @@
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
+ # TODO Setup a before save callback to generate route when there is no id
24
+ data.route ||= "#{@parent.route}/#{@parent._id}/#{model.pluralize @resource.toString()}" if @parent?
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
26
+ # Adds parent record to children side of association, if not set
27
+ # TODO check if this reference is unmade on instance elimination
28
+ data[@parent_resource] ||= @parent
29
+
30
+ # TODO store a singular copy of the resource for better performace
31
+ model[model.singularize @resource] data
32
+ push : ->
33
+ console.warn "#{@resource}.push is deprecated and will be removed, please use add instead"
34
+ Array.prototype.push.apply @, arguments
35
+ arguments[0]
36
+
37
+ length : 0
38
+ json : (methods, omissions) -> record.json(methods, omissions) for record in @
39
+
40
+ find : (id) -> return resource for resource in @ when resource._id is id
41
+
42
+ # TODO better support searching
43
+ filter : Array.prototype.filter || _?.filter
44
+
45
+
46
+ singular = # belongs_to, has_one ## TODO embeds_one, embedded_in
47
+ # @ = record
48
+ create: (data) -> model[@resource].create extend {}, @, data
49
+ # @ = record
50
+ # TODO convert to association proxy
51
+ build : (data) ->
52
+ # Adds child record of association to parent, and returns new
53
+ # record
54
+ @owner[@resource.toString()] = model[@resource.toString()] extend {}, @, data
55
+
56
+ descriptors =
57
+ belongs_to:
58
+ # TODO store association observer in association proxy, also
59
+ # update observable to support creating empty observers on object
60
+ # attributes
61
+ resource_id:
62
+ getter: -> @owner.observed[@resource + '_id']
63
+ setter: (resource_id) ->
64
+ # TODO check for association name in association proxy
65
+ association_name = @resource.toString()
66
+
67
+ # TODO faster nullifing association check
68
+ # TODO check if its usefull to only allow disassociating with null
69
+ # TODO notify nullification of associations
70
+ unless resource_id?
71
+ # If there is anything to nullify, undefine or falsify, do it
72
+ if @owner[association_name] or @owner[association_name + '_id']
73
+ @dirty = true
74
+ @owner[association_name] = null
75
+
76
+ return resource_id
77
+
78
+ # TODO Discover and update inverse side of association
79
+ # associated[@owner.resource.toString()] = @owner
80
+ current_resource_id = @owner.observed[association_name]?._id
81
+ if resource_id != current_resource_id
82
+
83
+ # For getter to read, we store conveniently on observable
84
+ # repository
85
+ @owner.observed[association_name + '_id'] = resource_id
86
+
87
+ # Nullify associated object, so next time user accesses it,
88
+ # association loader loads the new object
89
+ @owner.observed[association_name] = null
90
+
91
+ # If we have any listener associated with this property,
92
+ # notify it
93
+ # TODO implement notification api on observable
94
+ unless Object.observe
95
+ @owner.observation.observers[association_name + '_id']?.check_()
96
+ else
97
+ change = oldValue: current_resource_id, type: 'update', name: association_name + '_id', object: @owner
98
+ Object.getNotifier(@owner).notify change
99
+
100
+ resource_id
101
+
102
+ resource:
103
+ # TODO Use Auto build and Auto load as association options
104
+ getter: ->
105
+ # TODO allow custom association names
106
+ association_name = @resource.toString()
107
+ associated = @owner.observed[association_name]
108
+ associated_id = @owner.observed[association_name + '_id']
109
+
110
+ # Returns null depending on sustained state of resource and on
111
+ # retrievability of the resource
112
+ return associated || null unless associated?._id? or associated_id
113
+
114
+ # Returns imediatelly for resources on storage
115
+ # TODO make this extensible
116
+ return associated if associated?.sustained
117
+
118
+ # Auto build
119
+ resource = model[association_name]
120
+ unless resource
121
+ console.warn "descriptors.belongs_to.resource.getter: associated factory not found for model '#{association_name}' belonging to '#{@owner.resource}'"
122
+ return associated
123
+
124
+ # Search through stored resources to see if it is stored
125
+ associated = resource.find associated_id || associated._id
126
+
127
+ # Found associated in storage, update this model and return associated
128
+ return @owner.observed[association_name] = associated if associated
129
+
130
+ # Auto load
131
+ # Not found associated in storage
132
+ # TODO remote find or local find automatically, and implement find_or_initialize_by
133
+ associated ||= resource _id: associated_id # initialize and store a new record
134
+ associated.reload() # fetch resource
135
+
136
+ # Store temporary unloaded resource in this model
137
+ @owner.observed[association_name] = associated
138
+
139
+ # Called when associated record changes, so we can silently update the id
140
+ # TODO Get observer and notify through them
141
+ setter: (associated) ->
142
+ association_name = @resource.toString()
143
+ current_value = @owner.observed[association_name]
144
+
145
+ # Do nothing if the values are not changing
146
+ return if current_value == associated and !(current_value || associated)
147
+
148
+ @owner.observed[association_name] = associated
149
+ @owner.observed[association_name + '_id'] = if associated then associated._id else null
150
+
151
+ # TODO implement notification api on observable
152
+ unless Object.observe
153
+ @owner.observation.observers[association_name]?.check_()
154
+ else
155
+ change = oldValue: current_value, type: 'update', name: association_name, object: @owner
156
+ Object.getNotifier(@owner).notify change
157
+
158
+ change = oldValue: associated?._id, type: 'update', name: association_name + '_id', object: @owner
159
+ Object.getNotifier(@owner).notify change
160
+
161
+ associated
162
+
163
+
164
+ callbacks =
165
+ has_many:
166
+ # Forward association nested attributes
167
+ # TODO write attribute setter, and remove this code
168
+ nest_attributes: ->
169
+ # TODO only nest specified nested attributes on model definition
170
+ # TODO remove associations iteration, and pass throught parameter
171
+ # TODO DO not support '_attributes' property on instantiating!
172
+ association_names = model[@resource].has_many
173
+ if association_names
174
+ for association_name in association_names
175
+
176
+ # Instantiate new records for the association attributes
177
+ # TODO DO not support '_attributes' property on instantiating!
178
+ # TODO define setter for attributes
179
+ associations_attributes = @["#{association_name}_attributes"]
180
+ association = @[model.pluralize association_name]
181
+
182
+ if associations_attributes and associations_attributes.length
183
+
184
+ unless association
185
+ message = "has_many.nest_attributes: Association not found for #{association_name}. \n"
186
+ message += "did you set it on model declaration? \n has_many: #{association_name} "
187
+ throw message
188
+
189
+ # TODO store a singular copy of the resource for better performace
190
+ association.resource = model.singularize association.resource
191
+ association.add.apply association, associations_attributes
192
+ association.resource = model.pluralize association.resource
193
+
194
+ delete @["#{association_name}_attributes"]
195
+
196
+ # TODO Update route after setting the id
197
+ # TODO Update route association only once for each associated record
198
+ update_association: (data) ->
199
+ id = @_id || data && (data._id || data.id)
200
+
201
+ # Keep trying until we have a id
202
+ return unless id
203
+
204
+ for association_name in model[@resource.toString()].has_many
205
+ pluralized_association = model.pluralize association_name
206
+ association = @[pluralized_association]
207
+ # TODO setter of association.route
208
+ # to automatically update associated records
209
+ unless association.route
210
+ association.route = "/#{model.pluralize @resource.toString()}/#{id}/#{model.pluralize association.resource}"
211
+
212
+ for associated in association when not associated.route and associated.parent?
213
+ associated.route = "/#{model.pluralize @resource.toString()}/#{id}/#{model.pluralize association.resource}"
214
+
215
+ true
216
+ autosave: ->
217
+ throw 'Not implemented yet'
218
+ # @save()
219
+
220
+ has_one:
221
+ # Forward association nested attributes
222
+ # TODO write attribute setter, and remove this code
223
+ nest_attributes: ->
224
+ # TODO only nest specified nested attributes on model definition
225
+ # TODO convert to associations instead of association name
226
+ # TODO remove associations iteration, and pass throught parameter
227
+ # TODO DO not support '_attributes' property on instantiating!
228
+ association_names = model[@resource].has_one
229
+ if association_names
230
+ for association_name in association_names
231
+ associations_attributes = @["#{association_name}_attributes"]
232
+ if associations_attributes
233
+ @[association_name] = @["build_#{association_name}"] associations_attributes
234
+ delete @["#{association_name}_attributes"]
235
+
236
+
237
+ # TODO Better association segregation
238
+ associable =
239
+ model:
240
+
241
+ # @ = model instance
242
+ # param definition modable
243
+ blender: (definition) ->
244
+ {model} = associable
245
+
246
+ @create_after_hooks = model.create_after_hooks
247
+ @create_before_hooks = model.create_before_hooks
248
+
249
+ # TODO better default definition of associations
250
+ @has_many = [@has_many ] if @has_many and $.type(@has_many) != 'array'
251
+ @has_one = [@has_one ] if @has_one and $.type(@has_one) != 'array'
252
+ @belongs_to = [@belongs_to] if @belongs_to and $.type(@belongs_to) != 'array'
253
+
254
+ @has_many ||= []
255
+ @has_one ||= []
256
+ @belongs_to ||= []
257
+
258
+ true
259
+
260
+
261
+ # TODO better organisation of this code
262
+ # inside this function: @ = record (running on after_initialize)
263
+ create_after_hooks: (definition) ->
264
+
265
+ # TODO Rename options to definition
266
+ options = model[@resource.name || @resource.toString()]
267
+
268
+ # Create association methods
269
+ # Setup one to many association in model
270
+ if options.has_many
271
+
272
+ # TODO accept more options on has_many association creation
273
+ for resource in options.has_many
274
+ # unless model[resource]
275
+ # throw "Model not found for association with resource '#{resource}', on association 'has_many' "
276
+
277
+ # TODO instantiate default resources in has_many association
278
+ # @resource = model[resource].resource
279
+
280
+ # TODO Remember to clear association proxy when object is destroyed
281
+ association_proxy = resource: resource, parent_resource: @resource, parent: @
282
+ association_name = model.pluralize resource
283
+
284
+ # When deserializing has many associated resources from
285
+ # server, it is common to send as the association without
286
+ # attributes suffix
287
+ association_attributes = @[association_name] || []
288
+ @["#{association_name}_attributes"] ||= []
289
+ @["#{association_name}_attributes"] = @["#{association_name}_attributes"].concat association_attributes if association_attributes.length
290
+
291
+ # Create or Override sent attributes by the association proxy
292
+ @[association_name] = $.extend association_proxy, plural
293
+
294
+
295
+ # Update association attribute
296
+ @after 'saved', callbacks.has_many.update_association
297
+
298
+ # Remove nested attributes and convert them into actual records
299
+ callbacks.has_many.nest_attributes.call @
300
+
301
+ if options.has_one
302
+ for resource in options.has_one
303
+ # unless model[resource]
304
+ # throw "Model not found for association with resource '#{resource}', on association 'has_one' "
305
+
306
+ # TODO deprecate parent_resource
307
+ association_proxy = resource: resource, parent_resource: @resource, owner: @
308
+ association_proxy[@resource.toString()] = @
309
+
310
+ @["build_#{resource}" ] = $.proxy singular.build , association_proxy
311
+ @["create_#{resource}"] = $.proxy singular.create, association_proxy
312
+
313
+
314
+ # When deserializing has one associated resources from
315
+ # server, it is common to send as the association without
316
+ # attributes suffix
317
+ @["#{association_name}_attributes"] = $.extend @[association_name], @["#{association_name}_attributes"]
318
+
319
+ # Update association attribute
320
+ # TODO @after 'saved', callbacks.has_one.update_association
321
+
322
+ # Remove nested attributes and convert them into actual records
323
+ callbacks.has_one.nest_attributes.call @
324
+
325
+ # Externalize this to a file
326
+ if options.belongs_to
327
+ # TODO implement association reflection!
328
+ for resource in options.belongs_to
329
+ # unless model[resource]
330
+ # throw "Model not found for association with resource '#{resource}', on association 'belongs_to' "
331
+
332
+ # TODO put deprecation warning on parent key
333
+ association_proxy = resource: resource, parent_resource: @resource, parent: @, owner: @
334
+
335
+ # TODO see why this code is here, since we have the owner key
336
+ association_proxy[@resource.toString()] = @
337
+
338
+ @["build_#{resource}"] = $.proxy singular.build , association_proxy
339
+ @["create_#{resource}"] = $.proxy singular.create, association_proxy
340
+
341
+ # TODO copy from active record and better modularization of
342
+ # this internals
343
+ # To prevent association loading request we must nullify the
344
+ # association when subscribing
345
+ old_resource_id = @["#{resource}_id"]
346
+ old_dirty = @dirty
347
+ @["#{resource}_id"] = null
348
+
349
+ # TODO implement as a class
350
+ Object.defineProperty @, "#{resource}_id",
351
+ get: $.proxy descriptors.belongs_to.resource_id.getter, association_proxy
352
+ set: $.proxy descriptors.belongs_to.resource_id.setter, association_proxy
353
+ configurable: true
354
+
355
+ # Restore id after loader prevention has passed
356
+ @["#{resource}_id"] = old_resource_id
357
+ @dirty = old_dirty
358
+
359
+ # Execute relation attributes binding
360
+ # TODO validate bindings! When @resource._id != @["#{resource}_id"]
361
+ # TODO write test for this case
362
+ # if @["#{resource}_id"] and not @[resource]
363
+ # @publish "#{resource}_id", @["#{resource}_id"]
364
+
365
+ # TODO better organization of this code, probably transforming the
366
+ # association into a composable object inside this function: @ =
367
+ # record (running on before_initialize) Beware there is no
368
+ # advisable or observable features
369
+ # @ = model
370
+ # param record = record instance
371
+ create_before_hooks: (record) ->
372
+ definition = @
373
+
374
+ # TODO Externalize this to a file
375
+ if definition.belongs_to
376
+
377
+ # TODO implement association reflection!
378
+ for resource in definition.belongs_to
379
+ # unless model[resource]
380
+ # throw "Model not found for association with resource '#{resource}', on association 'belongs_to' "
381
+
382
+ # TODO put deprecation warning on parent key
383
+ association_proxy = resource: resource, parent_resource: @resource, owner: record
384
+
385
+ old_resource = record[resource]
386
+ old_resource_id = record[resource + '_id']
387
+
388
+ Object.defineProperty record, resource.toString(),
389
+ get: $.proxy descriptors.belongs_to.resource.getter, association_proxy
390
+ set: $.proxy descriptors.belongs_to.resource.setter, association_proxy
391
+ configurable: true
392
+
393
+ # Execute setter in order to do the apropriate actions to
394
+ # the previoulsy stored value in the association property
395
+ # TODO fix the prototype chain and remove this code
396
+ record.after_initialize.push (-> (@[resource] = old_resource) or (@[resource + '_id'] = old_resource_id))
397
+
398
+ # @ = record
399
+ record:
400
+ after_initialize: (attributes) ->
401
+ throw new Error 'resource must be defined in order to associate' unless @resource?
402
+ model[@resource.name || @resource.toString()].create_after_hooks.call @
403
+
404
+ before_initialize: (creation) ->
405
+ throw new Error 'resource must be defined in order to associate' unless @resource
406
+ model[@resource.name || @resource.toString()].create_before_hooks creation
407
+
408
+
409
+ # Extend indemma
410
+ model = root.model # TODO better way to get parent
411
+ model.mix (modelable) ->
412
+ modelable.after_mix.push associable.model.blender
413
+ modelable.record.before_initialize.push associable.record.before_initialize
414
+ modelable.record.after_initialize.push associable.record.after_initialize
415
+
416
+ # This allows to extendind the associable mixin
417
+ model.associable =
418
+ mix : (blender) ->
419
+ blender singular, plural
@@ -0,0 +1,47 @@
1
+ 'use strict'
2
+
3
+ dirtyable =
4
+ # TODO move ignored diryifing properties to the record
5
+ ignores: ['dirty', 'resource', 'route', 'initial_route', 'after_initialize', 'before_initialize', 'parent_resource', 'nested_attributes', 'reloading', 'ready', 'saving', 'saved', 'failed', 'salvation', 'sustained', 'element', 'default', 'lock', 'validate', 'validated', 'validation', 'errors', 'dirty', 'json']
6
+ reserved_filter: (name) -> @ignores.indexOf(name) == -1
7
+ record:
8
+ after_initialize: [ ->
9
+ @subscribe (added, removed, changed, past) ->
10
+ @dirty ||= !!Object.keys($.extend {}, added, removed, changed).filter(dirtyable.reserved_filter, dirtyable).length
11
+ ]
12
+
13
+ # Shim browsers without Object.observe
14
+ unless Object.observe
15
+
16
+ $.extend dirtyable,
17
+ descriptor:
18
+ get: -> @observed.dirty
19
+ set: (value) ->
20
+ @observed.dirty = value
21
+ @observation.scheduler.schedule()
22
+ value
23
+
24
+ dirtyable.record.after_initialize.push ->
25
+ Object.defineProperty @, 'dirty', dirtyable.descriptor
26
+
27
+ # Automatically dirt records without id
28
+ # FIXME
29
+ dirtyable.record.after_initialize.push ->
30
+ # TODO rename _id to id
31
+ @dirty = !!@_id
32
+
33
+
34
+
35
+ # Extend indemma
36
+ model = window.model # TODO better way to get parent
37
+ record = window.record # TODO better way to get parent
38
+
39
+ model.dirtyable = true
40
+
41
+ record.mix (recordable) ->
42
+ recordable.after_initialize = recordable.after_initialize.concat dirtyable.record.after_initialize
43
+
44
+ model.mix (modelable ) ->
45
+ # merge modelable , restful.model
46
+
47
+ `export default dirtyable`
@@ -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,34 @@
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
+ # TODO better caching check after resource initialization
16
+ # TODO think how to retrieve already stored resources
17
+ after_initialize: ->
18
+ if @_id
19
+ # TODO remove global model usage
20
+ {storage} = model[@resource.toString()]
21
+ storage.store @_id, @
22
+ else
23
+ # TODO check persistable configuration before attaching handlers
24
+ @after 'saved', handlers.store_after_saved
25
+
26
+ # Extend indemma
27
+ # TODO use stampit to extend record and model
28
+ model = window.model # TODO better way to get parent
29
+ record = window.record # TODO better way to get parent
30
+
31
+ model.persistable = true
32
+
33
+ model.mix (modelable) ->
34
+ 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
+ throw new TypeError "InvalidFind: #{@resource.toString()}.find was called with a falsey value" unless key
11
+ @storage.store key
12
+ every: (callback) -> callback @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,107 @@
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
+ # TODO Think of a better name, and move to a composable stampit item
28
+ # TODO Externalize route generatio so we can reuse in other files
29
+ descriptors =
30
+ route:
31
+ get: ->
32
+ # TODO use resource object on associations!
33
+ @resource = name: @resource if typeof @resource == 'string'
34
+
35
+ route = '/'
36
+ route += "#{@parent.route}/#{@parent._id}" + "/" if @parent?
37
+ route += @resource.scope + '/' if @resource.scope?
38
+
39
+ route += if @resource.singular then @resource.name else model.pluralize @resource.name
40
+
41
+ @route = route
42
+
43
+ configurable: true
44
+ # set: (value) -> @initial_route = value
45
+
46
+ # TODO Deprecated! Remove on 15/02/2014
47
+ # parent_id:
48
+ # get: -> @[@parent_resource]._id if @[@parent_resource]
49
+ # set: -> console.error 'Warning changing associations throught parent_id not allowed for security and style guide purposes' # TODO
50
+ # configurable: true
51
+ # enumerable: true
52
+
53
+ # TODO Think of a better name, and move to a composable stampit item
54
+ resourceable =
55
+ pluralize: (word, count, plural) ->
56
+ throw new TypeError "Invalid string passed to pluralize '#{word}'" unless word and word.length
57
+
58
+ unless word.indexOf('s') == word.length - 1
59
+ owl.pluralize word, count, plural
60
+ else
61
+ word
62
+
63
+ singularize: (word) ->
64
+ throw new TypeError "Invalid string passed to singularize '#{word}'" unless word and word.length
65
+
66
+ if word.lastIndexOf('s') == word.length - 1
67
+ word.substring 0, word.length - 1
68
+ else
69
+ word
70
+
71
+ initialize: ->
72
+
73
+ # Deprecated! Remove on 15/02/2014
74
+ # Set parent attribute and default nested route
75
+ # If you're using the associable plugin, this getter and setter will be overwritten!
76
+ # if @parent_resource
77
+ # Object.defineProperty @, "#{@parent_resource}_id", descriptors.parent_id
78
+
79
+ # Setup resource
80
+ resource_definition = {}
81
+ resource_definition = name: @resource if typeof @resource == 'string'
82
+ if typeof @resource == 'object'
83
+ # TODO deeper resource integration with record.coffee, and remove original reference
84
+ # To prevent reference lost and allow dinamic modification of resources
85
+ # we need to preserve the original reference
86
+ @resource.original_reference = @resource
87
+
88
+ resource_definition = @resource
89
+
90
+ # TODO remove mentions of @parent_resource and use only resource: {parent: ...}
91
+ resource_definition.parent = @parent_resource
92
+
93
+ @resource = resource resource_definition
94
+
95
+ # TODO Support route parsing, and change route to /parents/:id/childrens
96
+ @route ? Object.defineProperty @, 'route', descriptors.route
97
+
98
+
99
+ # Extend indemma
100
+ model = window.model # TODO better way to get parent
101
+
102
+ model.mix (modelable) ->
103
+ modelable.record.after_initialize.unshift resourceable.initialize
104
+ modelable.after_mix.unshift resourceable.initialize
105
+
106
+ model.singularize = resourceable.singularize
107
+ model.pluralize = resourceable.pluralize