joosy 0.1.0.alpha → 1.0.0.RC1
Sign up to get free protection for your applications and to get access to all the features.
- data/.codoopts +5 -0
- data/.gitignore +2 -0
- data/Gemfile +15 -2
- data/Gemfile.lock +102 -81
- data/Guardfile +16 -16
- data/LICENSE +22 -0
- data/MIT-LICENSE +2 -2
- data/README.md +118 -0
- data/app/assets/javascripts/joosy/core/application.js.coffee +53 -0
- data/app/assets/javascripts/joosy/core/form.js.coffee +338 -0
- data/app/assets/javascripts/joosy/core/helpers/form.js.coffee +72 -0
- data/app/assets/javascripts/joosy/core/helpers/view.js.coffee +42 -0
- data/app/assets/javascripts/joosy/core/helpers/widgets.js.coffee +14 -0
- data/app/assets/javascripts/joosy/core/joosy.js.coffee +184 -0
- data/app/assets/javascripts/joosy/core/layout.js.coffee +168 -0
- data/app/assets/javascripts/joosy/core/modules/container.js.coffee +124 -0
- data/app/assets/javascripts/joosy/core/modules/events.js.coffee +122 -0
- data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
- data/app/assets/javascripts/joosy/core/modules/log.js.coffee +36 -0
- data/app/assets/javascripts/joosy/core/modules/module.js.coffee +117 -0
- data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +200 -0
- data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +46 -0
- data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +87 -0
- data/app/assets/javascripts/joosy/core/page.js.coffee +387 -0
- data/app/assets/javascripts/joosy/core/preloader.js.coffee +13 -0
- data/app/assets/javascripts/joosy/core/resource/collection.js.coffee +175 -0
- data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +303 -0
- data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +244 -0
- data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +24 -0
- data/app/assets/javascripts/joosy/core/router.js.coffee +201 -0
- data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +37 -0
- data/app/assets/javascripts/joosy/core/widget.js.coffee +85 -0
- data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +169 -0
- data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +56 -0
- data/{vendor → app}/assets/javascripts/joosy.js.coffee +0 -1
- data/app/helpers/joosy/sprockets_helper.rb +39 -12
- data/joosy.gemspec +4 -3
- data/lib/joosy/rails/engine.rb +12 -1
- data/lib/joosy/rails/version.rb +2 -2
- data/lib/joosy.rb +9 -0
- data/lib/rails/generators/joosy/application_generator.rb +15 -3
- data/lib/rails/generators/joosy/joosy_base.rb +2 -2
- data/lib/rails/generators/joosy/layout_generator.rb +8 -1
- data/lib/rails/generators/joosy/page_generator.rb +21 -6
- data/lib/rails/generators/joosy/preloader_generator.rb +14 -7
- data/lib/rails/generators/joosy/resource_generator.rb +29 -0
- data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +4 -0
- data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +1 -0
- data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +1 -1
- data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -1
- data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +3 -3
- data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +22 -0
- data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app/routes.js.coffee +7 -1
- data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +2 -0
- data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +7 -0
- data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -2
- data/lib/rails/generators/joosy/templates/app.js.coffee +4 -0
- data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +9 -12
- data/lib/rails/generators/joosy/templates/app_resources_predefiner.js.coffee.erb +11 -0
- data/lib/rails/generators/joosy/templates/preload.html.erb +5 -6
- data/lib/rails/generators/joosy/templates/preload.html.haml +3 -5
- data/lib/rails/generators/joosy/widget_generator.rb +8 -1
- data/lib/rails/resources_with_joosy.rb +11 -0
- data/spec/javascripts/helpers/spec_helper.js.coffee +25 -0
- data/spec/javascripts/joosy/core/application_spec.js.coffee +40 -0
- data/spec/javascripts/joosy/core/form_spec.js.coffee +200 -0
- data/spec/javascripts/joosy/core/helpers/forms_spec.js.coffee +103 -0
- data/spec/javascripts/joosy/core/helpers/view_spec.js.coffee +10 -0
- data/spec/javascripts/joosy/core/joosy_spec.js.coffee +97 -0
- data/spec/javascripts/joosy/core/layout_spec.js.coffee +50 -0
- data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +32 -27
- data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +55 -18
- data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +28 -27
- data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +3 -3
- data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +6 -15
- data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +203 -0
- data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +12 -7
- data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +31 -17
- data/spec/javascripts/joosy/core/page_spec.js.coffee +178 -0
- data/spec/javascripts/joosy/core/resource/collection_spec.js.coffee +84 -0
- data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +149 -0
- data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +31 -0
- data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +171 -0
- data/spec/javascripts/joosy/core/router_spec.js.coffee +143 -0
- data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +25 -0
- data/spec/javascripts/joosy/core/widget_spec.js.coffee +40 -0
- data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +36 -0
- data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +16 -0
- data/spec/javascripts/support/assets/coolface.jpg +0 -0
- data/spec/javascripts/support/assets/okay.jpg +0 -0
- data/spec/javascripts/support/assets/test.js +1 -0
- data/spec/javascripts/support/sinon-ie-1.3.1.js +82 -0
- data/vendor/assets/javascripts/jquery.form.js +978 -963
- data/vendor/assets/javascripts/metamorph.js +409 -0
- data/vendor/assets/javascripts/sugar.js +1057 -366
- metadata +95 -50
- data/README.rdoc +0 -3
- data/lib/joosy/forms.rb +0 -47
- data/lib/joosy-rails.rb +0 -5
- data/lib/rails/generators/joosy/templates/preload.html.slim +0 -21
- data/tmp/javascripts/.gitignore +0 -1
- data/tmp/spec/javascripts/helpers/.gitignore +0 -1
- data/vendor/assets/javascripts/base64.js +0 -135
- data/vendor/assets/javascripts/inflection.js +0 -656
- data/vendor/assets/javascripts/joosy/core/application.js.coffee +0 -26
- data/vendor/assets/javascripts/joosy/core/form.js.coffee +0 -87
- data/vendor/assets/javascripts/joosy/core/joosy.js.coffee +0 -62
- data/vendor/assets/javascripts/joosy/core/layout.js.coffee +0 -38
- data/vendor/assets/javascripts/joosy/core/modules/container.js.coffee +0 -51
- data/vendor/assets/javascripts/joosy/core/modules/events.js.coffee +0 -17
- data/vendor/assets/javascripts/joosy/core/modules/filters.js.coffee +0 -39
- data/vendor/assets/javascripts/joosy/core/modules/log.js.coffee +0 -12
- data/vendor/assets/javascripts/joosy/core/modules/module.js.coffee +0 -28
- data/vendor/assets/javascripts/joosy/core/modules/time_manager.js.coffee +0 -23
- data/vendor/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +0 -45
- data/vendor/assets/javascripts/joosy/core/page.js.coffee +0 -136
- data/vendor/assets/javascripts/joosy/core/resource/rest.js.coffee +0 -69
- data/vendor/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +0 -42
- data/vendor/assets/javascripts/joosy/core/router.js.coffee +0 -75
- data/vendor/assets/javascripts/joosy/core/widget.js.coffee +0 -35
- data/vendor/assets/javascripts/joosy/preloader/development.js.coffee +0 -27
- data/vendor/assets/javascripts/joosy/preloader/production.js.coffee +0 -84
@@ -0,0 +1,175 @@
|
|
1
|
+
#
|
2
|
+
# Basic collection of Resources.
|
3
|
+
# Turns JSON array into array of Resources and manages them.
|
4
|
+
#
|
5
|
+
# @note You should not use Collection directly. It will be
|
6
|
+
# automatically created by things like {Joosy.Resource.Generic.map}
|
7
|
+
# or {Joosy.Resource.REST.find}.
|
8
|
+
#
|
9
|
+
# @example Basic sample
|
10
|
+
# class R extends Joosy.Resource.Generic
|
11
|
+
# @entity 'r'
|
12
|
+
#
|
13
|
+
# collection = new Joosy.Resource.Collection(R)
|
14
|
+
#
|
15
|
+
# collection.load [{foo: 'bar'}, {foo: 'baz'}]
|
16
|
+
# collection.each (resource) ->
|
17
|
+
# resource('foo')
|
18
|
+
#
|
19
|
+
# @include Joosy.Modules.Events
|
20
|
+
#
|
21
|
+
class Joosy.Resource.Collection extends Joosy.Module
|
22
|
+
@include Joosy.Modules.Events
|
23
|
+
|
24
|
+
#
|
25
|
+
# Allows to modify data before it gets stored
|
26
|
+
#
|
27
|
+
# @note Supposed to be used in descendants
|
28
|
+
#
|
29
|
+
# @param [Function] action `(Object) -> Object` to call
|
30
|
+
#
|
31
|
+
@beforeLoad: (action) -> @::__beforeLoad = action
|
32
|
+
|
33
|
+
#
|
34
|
+
# Sets the default model for collection
|
35
|
+
#
|
36
|
+
# @note Supposed to be used in descendants
|
37
|
+
#
|
38
|
+
# @param [Class] model Model class
|
39
|
+
#
|
40
|
+
@model: (model) -> @::model = model
|
41
|
+
|
42
|
+
#
|
43
|
+
# Modelized data storage
|
44
|
+
#
|
45
|
+
data: []
|
46
|
+
|
47
|
+
#
|
48
|
+
# If model param was empty it will fallback to `@model`
|
49
|
+
# If both param and `@model` were empty it will throw an exception.
|
50
|
+
#
|
51
|
+
# @param [Class] model Resource class which this collection will handle
|
52
|
+
#
|
53
|
+
constructor: (model=false) ->
|
54
|
+
@model = model if model
|
55
|
+
|
56
|
+
if !@model
|
57
|
+
throw new Error "#{Joosy.Module.__className @}> model can't be empty"
|
58
|
+
|
59
|
+
#
|
60
|
+
# Clears the storage and attempts to import given array
|
61
|
+
#
|
62
|
+
# @param [Array, Hash] entities Array of entities to import.
|
63
|
+
# If hash was given will seek for moodel name camelized and pluralized.
|
64
|
+
# @param [Boolean] notify Indicates whether to trigger 'changed' event
|
65
|
+
#
|
66
|
+
# @return [Joosy.Resource.Collection] Returns self.
|
67
|
+
#
|
68
|
+
load: (entities, notify=true) ->
|
69
|
+
if @__beforeLoad?
|
70
|
+
entities = @__beforeLoad entities
|
71
|
+
|
72
|
+
@data = @modelize entities
|
73
|
+
|
74
|
+
@trigger 'changed' if notify
|
75
|
+
this
|
76
|
+
|
77
|
+
#
|
78
|
+
# Turns Objects array into array of Resources
|
79
|
+
#
|
80
|
+
# @param [Array] collection Array of Objects
|
81
|
+
#
|
82
|
+
modelize: (collection) ->
|
83
|
+
root = @model::__entityName.pluralize()
|
84
|
+
|
85
|
+
if collection not instanceof Array
|
86
|
+
collection = collection?[root.camelize(false)]
|
87
|
+
|
88
|
+
if collection not instanceof Array
|
89
|
+
throw new Error "Can not read incoming JSON"
|
90
|
+
|
91
|
+
collection.map (x) =>
|
92
|
+
@model.build x
|
93
|
+
|
94
|
+
#
|
95
|
+
# Calls callback for each Resource inside Collection
|
96
|
+
#
|
97
|
+
# @param [Function] callback `(mixed) -> mixed` to call for each Resource in collection
|
98
|
+
#
|
99
|
+
each: (callback) ->
|
100
|
+
@data.each callback
|
101
|
+
|
102
|
+
#
|
103
|
+
# Returns number of Resources inside Collection
|
104
|
+
#
|
105
|
+
size: ->
|
106
|
+
@data.length
|
107
|
+
|
108
|
+
#
|
109
|
+
# Gets first resource matching description (see Sugar.js Array#find)
|
110
|
+
#
|
111
|
+
# @param [Function] description Callback matcher
|
112
|
+
#
|
113
|
+
# @return [Joosy.Resource.Generic]
|
114
|
+
#
|
115
|
+
find: (description) ->
|
116
|
+
@data.find description
|
117
|
+
|
118
|
+
#
|
119
|
+
# Gets resource by id
|
120
|
+
#
|
121
|
+
# @param [Integer] id Id to find
|
122
|
+
#
|
123
|
+
# @return [Joosy.Resource.Generic]
|
124
|
+
#
|
125
|
+
findById: (id) ->
|
126
|
+
@data.find (x) -> x.id().toString() == id.toString()
|
127
|
+
|
128
|
+
#
|
129
|
+
# Gets resource by its index inside collection
|
130
|
+
#
|
131
|
+
# @param [Integer] i Index
|
132
|
+
#
|
133
|
+
# @return [Joosy.Resource.Generic]
|
134
|
+
#
|
135
|
+
at: (i) ->
|
136
|
+
@data[i]
|
137
|
+
|
138
|
+
#
|
139
|
+
# Removes resource from collection by its index or by === comparison
|
140
|
+
#
|
141
|
+
# @param [Integer] target Index
|
142
|
+
# @param [Resource] target Resource by itself
|
143
|
+
# @param [Boolean] notify Indicates whether to trigger 'changed' event
|
144
|
+
#
|
145
|
+
# @return [Joosy.Resource.Generic] Removed element
|
146
|
+
#
|
147
|
+
remove: (target, notify=true) ->
|
148
|
+
if Object.isNumber target
|
149
|
+
index = target
|
150
|
+
else
|
151
|
+
index = @data.indexOf target
|
152
|
+
if index >= 0
|
153
|
+
result = @data.splice(index, 1)[0]
|
154
|
+
if notify
|
155
|
+
@trigger 'changed'
|
156
|
+
result
|
157
|
+
|
158
|
+
#
|
159
|
+
# Adds resource to collection to given index or to the end
|
160
|
+
#
|
161
|
+
# @param [Resource] element Resource to add
|
162
|
+
# @param [Integer] index Index to add to. If omited will be pushed to the end
|
163
|
+
# @param [Boolean] notify Indicates whether to trigger 'changed' event
|
164
|
+
#
|
165
|
+
# @return [Joosy.Resource.Generic] Added element
|
166
|
+
#
|
167
|
+
add: (element, index=false, notify=true) ->
|
168
|
+
if index
|
169
|
+
@data.splice index, 0, element
|
170
|
+
else
|
171
|
+
@data.push element
|
172
|
+
|
173
|
+
if notify
|
174
|
+
@trigger 'changed'
|
175
|
+
element
|
@@ -0,0 +1,303 @@
|
|
1
|
+
#
|
2
|
+
# Basic data wrapper with triggering and entity name binding
|
3
|
+
#
|
4
|
+
# @example Basic usage
|
5
|
+
# class R extends Joosy.Resource.Generic
|
6
|
+
# @entity 'r'
|
7
|
+
#
|
8
|
+
# @beforeLoad (data) ->
|
9
|
+
# data.real = true
|
10
|
+
#
|
11
|
+
# r = R.build {r: {foo: {bar: 'baz'}}}
|
12
|
+
#
|
13
|
+
# r('foo') # {baz: 'baz'}
|
14
|
+
# r('real') # true
|
15
|
+
# r('foo.bar') # baz
|
16
|
+
# r('foo.bar', 'fluffy') # triggers 'changed'
|
17
|
+
#
|
18
|
+
# @include Joosy.Modules.Log
|
19
|
+
# @include Joosy.Modules.Events
|
20
|
+
#
|
21
|
+
class Joosy.Resource.Generic extends Joosy.Module
|
22
|
+
@include Joosy.Modules.Log
|
23
|
+
@include Joosy.Modules.Events
|
24
|
+
|
25
|
+
#
|
26
|
+
# Default primary key field 'id'
|
27
|
+
#
|
28
|
+
__primaryKey: 'id'
|
29
|
+
|
30
|
+
__source: false
|
31
|
+
|
32
|
+
@resetIdentity: ->
|
33
|
+
Joosy.Resource.Generic.identity = {}
|
34
|
+
|
35
|
+
#
|
36
|
+
# Allows to modify data before it gets stored.
|
37
|
+
# You can define several beforeLoad filters that will be chained.
|
38
|
+
#
|
39
|
+
# @param [Function] action `(Object) -> Object` to call
|
40
|
+
#
|
41
|
+
@beforeLoad: (action) ->
|
42
|
+
unless @::hasOwnProperty '__beforeLoads'
|
43
|
+
@::__beforeLoads = [].concat @.__super__.__beforeLoads || []
|
44
|
+
@::__beforeLoads.push action
|
45
|
+
|
46
|
+
#
|
47
|
+
# Sets the field containing primary key.
|
48
|
+
#
|
49
|
+
# @note It has no direct use inside the REST resource itself and can be omited.
|
50
|
+
# But it usually should not since we have plans on adding some kind of Identity Map to Joosy.
|
51
|
+
#
|
52
|
+
# @param [String] primary Name of the field
|
53
|
+
#
|
54
|
+
@primaryKey: (primaryKey) -> @::__primaryKey = primaryKey
|
55
|
+
|
56
|
+
@source: (location) ->
|
57
|
+
@__source = location
|
58
|
+
|
59
|
+
#
|
60
|
+
# Creates the proxy of current resource binded as a child of given entity
|
61
|
+
#
|
62
|
+
@at: (entity) ->
|
63
|
+
#
|
64
|
+
# Class inheritance used to create proxy
|
65
|
+
#
|
66
|
+
# @private
|
67
|
+
#
|
68
|
+
class clone extends this
|
69
|
+
|
70
|
+
if entity instanceof Joosy.Resource.Generic
|
71
|
+
clone.__source = entity.memberPath()
|
72
|
+
else
|
73
|
+
clone.__source = entity
|
74
|
+
|
75
|
+
clone
|
76
|
+
|
77
|
+
#
|
78
|
+
# Sets the entity text name:
|
79
|
+
# required to do some magic like skipping the root node.
|
80
|
+
#
|
81
|
+
# @param [String] name Singular name of resource
|
82
|
+
#
|
83
|
+
@entity: (name) -> @::__entityName = name
|
84
|
+
|
85
|
+
#
|
86
|
+
# Sets the collection to use
|
87
|
+
#
|
88
|
+
# @note By default will try to seek for `EntityNamesCollection`.
|
89
|
+
# Will fallback to {Joosy.Resource.Collection}
|
90
|
+
#
|
91
|
+
# @param [Class] klass Class to assign as collection
|
92
|
+
#
|
93
|
+
@collection: (klass) -> @::__collection = -> klass
|
94
|
+
|
95
|
+
#
|
96
|
+
# Implements {Joosy.Resource.Generic.collection} default behavior.
|
97
|
+
#
|
98
|
+
__collection: ->
|
99
|
+
named = @__entityName.camelize().pluralize() + 'Collection'
|
100
|
+
if window[named] then window[named] else Joosy.Resource.Collection
|
101
|
+
|
102
|
+
#
|
103
|
+
# Dynamically creates collection of inline resources.
|
104
|
+
#
|
105
|
+
# Inline resources share the instance with direct data and therefore can be used
|
106
|
+
# to handle inline changes with triggers and all that resources stuff
|
107
|
+
#
|
108
|
+
# @example Basic usage
|
109
|
+
# class Zombie extends Joosy.Resource.Generic
|
110
|
+
# @entity 'zombie'
|
111
|
+
# class Puppy extends Joosy.Resource.Generic
|
112
|
+
# @entity 'puppy'
|
113
|
+
# @map 'zombies'
|
114
|
+
#
|
115
|
+
# p = Puppy.build {zombies: [{foo: 'bar'}]}
|
116
|
+
#
|
117
|
+
# p('zombies') # Direct access: [{foo: 'bar'}]
|
118
|
+
# p.zombies # Wrapped Collection of Zombie instances
|
119
|
+
# p.zombies.at(0)('foo') # bar
|
120
|
+
#
|
121
|
+
# @param [String] name Pluralized name of property to define
|
122
|
+
# @param [Class] klass Resource class to instantiate
|
123
|
+
#
|
124
|
+
@map: (name, klass=false) ->
|
125
|
+
unless klass
|
126
|
+
klass = window[name.singularize().camelize()]
|
127
|
+
|
128
|
+
if !klass
|
129
|
+
throw new Error "#{Joosy.Module.__className @}> class can not be detected for '#{name}' mapping"
|
130
|
+
|
131
|
+
@beforeLoad (data) ->
|
132
|
+
@__map(data, name, klass)
|
133
|
+
|
134
|
+
#
|
135
|
+
# Wraps instance of resource inside shim-function allowing to track
|
136
|
+
# data changes. See class example
|
137
|
+
#
|
138
|
+
# @return [Joosy.Resource.Generic]
|
139
|
+
#
|
140
|
+
@build: (data={}) ->
|
141
|
+
klass = @::__entityName
|
142
|
+
|
143
|
+
Joosy.Resource.Generic.identity ||= {}
|
144
|
+
Joosy.Resource.Generic.identity[klass] ||= {}
|
145
|
+
|
146
|
+
shim = ->
|
147
|
+
shim.__call.apply shim, arguments
|
148
|
+
|
149
|
+
if shim.__proto__
|
150
|
+
shim.__proto__ = @prototype
|
151
|
+
else
|
152
|
+
for key, value of @prototype
|
153
|
+
shim[key] = value
|
154
|
+
|
155
|
+
shim.constructor = @
|
156
|
+
|
157
|
+
if Object.isNumber(data) || Object.isString(data)
|
158
|
+
id = data
|
159
|
+
data = {}
|
160
|
+
data[shim.__primaryKey] = id
|
161
|
+
|
162
|
+
if Joosy.Application.identity
|
163
|
+
id = data[shim.__primaryKey]
|
164
|
+
|
165
|
+
if id? && Joosy.Resource.Generic.identity[klass][id]
|
166
|
+
shim = Joosy.Resource.Generic.identity[klass][id]
|
167
|
+
shim.load data
|
168
|
+
else
|
169
|
+
@apply shim, [data]
|
170
|
+
Joosy.Resource.Generic.identity[klass][id] = shim
|
171
|
+
else
|
172
|
+
@apply shim, [data]
|
173
|
+
|
174
|
+
shim
|
175
|
+
|
176
|
+
#
|
177
|
+
# Should NOT be called directly, use {::build} instead
|
178
|
+
#
|
179
|
+
# @private
|
180
|
+
# @param [Object] data Data to store
|
181
|
+
#
|
182
|
+
constructor: (data={}) ->
|
183
|
+
@__fillData data, false
|
184
|
+
|
185
|
+
id: ->
|
186
|
+
@data[@__primaryKey]
|
187
|
+
|
188
|
+
knownAttributes: ->
|
189
|
+
@data.keys()
|
190
|
+
|
191
|
+
#
|
192
|
+
# Set the resource data manually
|
193
|
+
#
|
194
|
+
# @param [Object] data Data to store
|
195
|
+
#
|
196
|
+
# @return [Joosy.Resource.Generic] Returns self
|
197
|
+
#
|
198
|
+
load: (data) ->
|
199
|
+
@__fillData data
|
200
|
+
return this
|
201
|
+
|
202
|
+
#
|
203
|
+
# Getter for wrapped data
|
204
|
+
#
|
205
|
+
# @param [String] path Attribute name to get. Can contain dots to get inline Objects values
|
206
|
+
# @return [mixed]
|
207
|
+
#
|
208
|
+
__get: (path) ->
|
209
|
+
target = @__callTarget path
|
210
|
+
|
211
|
+
if target[0] instanceof Joosy.Resource.Generic
|
212
|
+
return target[0](target[1])
|
213
|
+
else
|
214
|
+
return target[0][target[1]]
|
215
|
+
|
216
|
+
#
|
217
|
+
# Setter for wrapped data, triggers `changed` event.
|
218
|
+
#
|
219
|
+
# @param [String] path Attribute name to set. Can contain dots to get inline Objects values
|
220
|
+
# @param [mixed] value Value to set
|
221
|
+
#
|
222
|
+
__set: (path, value) ->
|
223
|
+
target = @__callTarget path
|
224
|
+
|
225
|
+
if target[0] instanceof Joosy.Resource.Generic
|
226
|
+
target[0](target[1], value)
|
227
|
+
else
|
228
|
+
target[0][target[1]] = value
|
229
|
+
|
230
|
+
@trigger 'changed'
|
231
|
+
null
|
232
|
+
|
233
|
+
#
|
234
|
+
# Locates the actual instance of attribute path `foo.bar` from get/set
|
235
|
+
#
|
236
|
+
# @param [String] path Path to the attribute (`foo.bar`)
|
237
|
+
# @return [Array] Instance of object containing last step of path and keyword for required field
|
238
|
+
#
|
239
|
+
__callTarget: (path) ->
|
240
|
+
if path.has(/\./) && !@data[path]?
|
241
|
+
path = path.split '.'
|
242
|
+
keyword = path.pop()
|
243
|
+
target = @data
|
244
|
+
|
245
|
+
for part in path
|
246
|
+
target[part] ||= {}
|
247
|
+
if target instanceof Joosy.Resource.Generic
|
248
|
+
target = target(part)
|
249
|
+
else
|
250
|
+
target = target[part]
|
251
|
+
|
252
|
+
[target, keyword]
|
253
|
+
else
|
254
|
+
[@data, path]
|
255
|
+
|
256
|
+
#
|
257
|
+
# Wrapper for {Joosy.Resource.Generic.build} magic
|
258
|
+
#
|
259
|
+
__call: (path, value) ->
|
260
|
+
if arguments.length > 1
|
261
|
+
@__set path, value
|
262
|
+
else
|
263
|
+
@__get path
|
264
|
+
|
265
|
+
#
|
266
|
+
# Defines how exactly prepared data should be saved
|
267
|
+
#
|
268
|
+
# @param [Object] data Raw data to store
|
269
|
+
#
|
270
|
+
__fillData: (data, notify=true) ->
|
271
|
+
@raw = data
|
272
|
+
@data = {} unless @hasOwnProperty 'data'
|
273
|
+
|
274
|
+
Joosy.Module.merge @data, @__prepareData(data)
|
275
|
+
|
276
|
+
@trigger 'changed' if notify
|
277
|
+
|
278
|
+
null
|
279
|
+
|
280
|
+
#
|
281
|
+
# Prepares raw data: cuts the root node if it exists, runs before filters
|
282
|
+
#
|
283
|
+
# @param [Hash] data Raw data to prepare
|
284
|
+
# @return [Hash]
|
285
|
+
#
|
286
|
+
__prepareData: (data) ->
|
287
|
+
if Object.isObject(data) && Object.keys(data).length == 1 && @__entityName
|
288
|
+
name = @__entityName.camelize(false)
|
289
|
+
data = data[name] if data[name]
|
290
|
+
|
291
|
+
if @__beforeLoads?
|
292
|
+
data = bl.call(this, data) for bl in @__beforeLoads
|
293
|
+
|
294
|
+
data
|
295
|
+
|
296
|
+
__map: (data, name, klass) ->
|
297
|
+
if Object.isArray data[name]
|
298
|
+
entry = new (klass::__collection()) klass
|
299
|
+
entry.load data[name]
|
300
|
+
data[name] = entry
|
301
|
+
else if Object.isObject data[name]
|
302
|
+
data[name] = klass.build data[name]
|
303
|
+
data
|