nali 0.4.2 → 0.4.3
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.
- data/lib/client/javascripts/nali/application.js.coffee +4 -4
- data/lib/client/javascripts/nali/collection.js.coffee +53 -53
- data/lib/client/javascripts/nali/connection.js.coffee +39 -39
- data/lib/client/javascripts/nali/controller.js.coffee +12 -12
- data/lib/client/javascripts/nali/model.js.coffee +56 -57
- data/lib/client/javascripts/nali/nali.js.coffee +22 -22
- data/lib/client/javascripts/nali/notice.js.coffee +7 -6
- data/lib/client/javascripts/nali/router.js.coffee +11 -18
- data/lib/client/javascripts/nali/view.js.coffee +102 -93
- data/lib/nali/clients.rb +2 -2
- data/lib/nali/connection.rb +4 -4
- data/lib/nali/controller.rb +2 -2
- data/lib/nali/helpers.rb +1 -1
- data/lib/nali/model.rb +1 -1
- data/lib/nali/tasks.rb +3 -0
- data/lib/nali/version.rb +1 -1
- metadata +2 -2
@@ -12,21 +12,21 @@ Nali.extend Application:
|
|
12
12
|
run: ( options ) ->
|
13
13
|
@::starting()
|
14
14
|
@[ key ] = value for key, value of options
|
15
|
-
@
|
15
|
+
@_onReadyDOM ->
|
16
16
|
@::_ = @domEngine
|
17
17
|
@htmlContainer = @_ @htmlContainer
|
18
18
|
@setTitle @title
|
19
19
|
@Router.start()
|
20
|
-
@
|
20
|
+
@_runConnection()
|
21
21
|
|
22
|
-
|
22
|
+
_onReadyDOM: ( callback ) ->
|
23
23
|
document.addEventListener 'DOMContentLoaded', =>
|
24
24
|
document.removeEventListener 'DOMContentLoaded', arguments.callee, false
|
25
25
|
callback.call @
|
26
26
|
, false
|
27
27
|
@
|
28
28
|
|
29
|
-
|
29
|
+
_runConnection: ->
|
30
30
|
if @useWebSockets
|
31
31
|
@Connection.subscribe @, 'open', @onConnectionOpen
|
32
32
|
@Connection.subscribe @, 'close', @onConnectionClose
|
@@ -1,19 +1,19 @@
|
|
1
1
|
Nali.extend Collection:
|
2
2
|
|
3
|
-
toShowViews: []
|
4
|
-
visibleViews: []
|
5
|
-
length: 0
|
6
|
-
|
7
3
|
cloning: ->
|
8
|
-
@subscribeTo @Model, "create.#{ @model._name.lower() }",
|
9
|
-
@subscribeTo @Model, "update.#{ @model._name.lower() }",
|
10
|
-
@subscribeTo @Model, "destroy.#{ @model._name.lower() }", @
|
4
|
+
@subscribeTo @Model, "create.#{ @model._name.lower() }", @_onModelCreated
|
5
|
+
@subscribeTo @Model, "update.#{ @model._name.lower() }", @_onModelUpdated
|
6
|
+
@subscribeTo @Model, "destroy.#{ @model._name.lower() }", @_onModelDestroyed
|
11
7
|
@adaptations = apply: [], cancel: []
|
12
|
-
@
|
13
|
-
@
|
8
|
+
@_ordering = {}
|
9
|
+
@_adaptCollection()
|
14
10
|
@refilter()
|
15
11
|
@
|
16
12
|
|
13
|
+
_toShowViews: []
|
14
|
+
_visibleViews: []
|
15
|
+
length: 0
|
16
|
+
|
17
17
|
refilter: ->
|
18
18
|
@model.each ( model ) =>
|
19
19
|
if isCorrect = model.isCorrect( @filters ) and not ( model in @ ) then @add model
|
@@ -23,34 +23,34 @@ Nali.extend Collection:
|
|
23
23
|
new: ( model, filters ) ->
|
24
24
|
@clone model: model, filters: filters
|
25
25
|
|
26
|
-
|
26
|
+
_onModelCreated: ( model ) ->
|
27
27
|
@add model if not @freezed and model.isCorrect @filters
|
28
28
|
@
|
29
29
|
|
30
|
-
|
30
|
+
_onModelUpdated: ( model ) ->
|
31
31
|
if model.written()
|
32
32
|
if model in @
|
33
33
|
if @freezed or model.isCorrect @filters
|
34
|
-
@
|
34
|
+
@_reorder()
|
35
35
|
@trigger 'update.model', model
|
36
36
|
else @remove model
|
37
37
|
else if not @freezed and model.isCorrect @filters
|
38
38
|
@add model
|
39
39
|
@
|
40
40
|
|
41
|
-
|
41
|
+
_onModelDestroyed: ( model ) ->
|
42
42
|
@remove model if model in @ and not @freezed
|
43
43
|
@
|
44
44
|
|
45
|
-
|
46
|
-
for name, method of @model when /^
|
45
|
+
_adaptCollection: ->
|
46
|
+
for name, method of @model when /^__\w+$/.test( name ) and typeof method is 'function'
|
47
47
|
do ( name, method ) =>
|
48
|
-
@[ name = name[
|
48
|
+
@[ name = name[ 2.. ] ] = ( args... ) =>
|
49
49
|
@each ( model ) -> model[ name ] args...
|
50
50
|
@
|
51
51
|
@
|
52
52
|
|
53
|
-
|
53
|
+
_adaptModel: ( model, type = 'apply' ) ->
|
54
54
|
adaptation.call @, model for adaptation in @adaptations[ type ]
|
55
55
|
@
|
56
56
|
|
@@ -63,17 +63,17 @@ Nali.extend Collection:
|
|
63
63
|
add: ( models... ) ->
|
64
64
|
for model in [].concat models...
|
65
65
|
Array::push.call @, model
|
66
|
-
@
|
67
|
-
@
|
66
|
+
@_adaptModel model
|
67
|
+
@_reorder()
|
68
68
|
@trigger 'update.length.add', model
|
69
69
|
@trigger 'update.length', 'add', model
|
70
70
|
@
|
71
71
|
|
72
72
|
remove: ( model ) ->
|
73
|
-
@
|
73
|
+
@_adaptModel model, 'cancel'
|
74
74
|
Array::splice.call @, @indexOf( model ), 1
|
75
75
|
@unsubscribeFrom model
|
76
|
-
@
|
76
|
+
@_reorder()
|
77
77
|
@trigger 'update.length.remove', model
|
78
78
|
@trigger 'update.length', 'remove', model
|
79
79
|
@
|
@@ -113,37 +113,37 @@ Nali.extend Collection:
|
|
113
113
|
filters[ name ] = value for name, value of @filters
|
114
114
|
@model.where filters
|
115
115
|
|
116
|
-
order: ( @
|
117
|
-
@
|
116
|
+
order: ( @_ordering ) ->
|
117
|
+
@_reorder()
|
118
118
|
@
|
119
119
|
|
120
|
-
|
121
|
-
if @
|
122
|
-
clearTimeout @
|
123
|
-
@
|
124
|
-
if typeof @
|
125
|
-
@sort @
|
120
|
+
_reorder: ->
|
121
|
+
if @_ordering.by?
|
122
|
+
clearTimeout @_ordering.timer if @_ordering.timer?
|
123
|
+
@_ordering.timer = setTimeout =>
|
124
|
+
if typeof @_ordering.by is 'function'
|
125
|
+
@sort @_ordering.by
|
126
126
|
else
|
127
127
|
@sort ( one, two ) =>
|
128
|
-
one = one[ @
|
129
|
-
two = two[ @
|
130
|
-
if @
|
128
|
+
one = one[ @_ordering.by ]
|
129
|
+
two = two[ @_ordering.by ]
|
130
|
+
if @_ordering.as is 'number'
|
131
131
|
one = + one
|
132
132
|
two = + two
|
133
|
-
if @
|
133
|
+
if @_ordering.as is 'string'
|
134
134
|
one = '' + one
|
135
135
|
two = '' + two
|
136
|
-
( if one > two then 1 else if one < two then -1 else 0 ) * ( if @
|
137
|
-
@
|
138
|
-
delete @
|
136
|
+
( if one > two then 1 else if one < two then -1 else 0 ) * ( if @_ordering.desc then -1 else 1 )
|
137
|
+
@_orderViews()
|
138
|
+
delete @_ordering.timer
|
139
139
|
, 5
|
140
140
|
@
|
141
141
|
|
142
|
-
|
143
|
-
if @
|
144
|
-
children = Array::slice.call @
|
142
|
+
_orderViews: ->
|
143
|
+
if @_inside
|
144
|
+
children = Array::slice.call @_inside.children
|
145
145
|
children.sort ( one, two ) => @indexOf( one.view.model ) - @indexOf( two.view.model )
|
146
|
-
@
|
146
|
+
@_inside.appendChild child for child in children
|
147
147
|
@
|
148
148
|
|
149
149
|
show: ( viewName, insertTo, isRelation = false ) ->
|
@@ -153,12 +153,12 @@ Nali.extend Collection:
|
|
153
153
|
view.subscribeTo @, 'reset', view.hide
|
154
154
|
else unless @visible
|
155
155
|
@visible = true
|
156
|
-
@
|
157
|
-
@
|
156
|
+
@_prepareViewToShow view
|
157
|
+
@_hideVisibleViews()
|
158
158
|
else
|
159
|
-
@::
|
159
|
+
@::_visibleViews.push view
|
160
160
|
view.show insertTo
|
161
|
-
@
|
161
|
+
@_inside ?= view.element[0].parentNode
|
162
162
|
, ( model ) ->
|
163
163
|
model.hide viewName
|
164
164
|
@
|
@@ -167,16 +167,16 @@ Nali.extend Collection:
|
|
167
167
|
model.hide viewName, delay for model in @
|
168
168
|
@
|
169
169
|
|
170
|
-
|
171
|
-
unless view in @::
|
172
|
-
@::
|
173
|
-
@
|
170
|
+
_prepareViewToShow: ( view ) ->
|
171
|
+
unless view in @::_toShowViews
|
172
|
+
@::_toShowViews.push view
|
173
|
+
@_prepareViewToShow layout if ( layout = view.layout() )?.childOf? 'View'
|
174
174
|
@
|
175
175
|
|
176
|
-
|
177
|
-
view.hide() for view in @::
|
178
|
-
@::
|
179
|
-
@::
|
176
|
+
_hideVisibleViews: ->
|
177
|
+
view.hide() for view in @::_visibleViews when not( view in @::_toShowViews )
|
178
|
+
@::_visibleViews = @::_toShowViews
|
179
|
+
@::_toShowViews = []
|
180
180
|
@
|
181
181
|
|
182
182
|
first: ->
|
@@ -186,7 +186,7 @@ Nali.extend Collection:
|
|
186
186
|
@[ @length - 1 ]
|
187
187
|
|
188
188
|
reset: ->
|
189
|
-
@
|
189
|
+
@_inside = null
|
190
190
|
@adaptations.length = 0
|
191
191
|
@trigger 'reset'
|
192
192
|
@
|
@@ -5,86 +5,86 @@ Nali.extend Connection:
|
|
5
5
|
@
|
6
6
|
|
7
7
|
open: ->
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
8
|
+
@_dispatcher = new WebSocket @Application.wsServer
|
9
|
+
@_dispatcher.onopen = ( event ) => @_identification()
|
10
|
+
@_dispatcher.onclose = ( event ) => @_onClose event
|
11
|
+
@_dispatcher.onerror = ( event ) => @_onError event
|
12
|
+
@_dispatcher.onmessage = ( event ) => @_onMessage JSON.parse event.data
|
13
|
+
@_keepAlive()
|
14
14
|
@
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
_keepAliveTimer: null
|
17
|
+
_journal: []
|
18
|
+
_reconnectDelay: 0
|
19
19
|
|
20
|
-
|
21
|
-
@
|
20
|
+
_onOpen: ->
|
21
|
+
@_reconnectDelay = 0
|
22
22
|
@trigger 'open'
|
23
23
|
|
24
|
-
|
24
|
+
_onError: ( event ) ->
|
25
25
|
console.warn 'Connection error %O', event
|
26
26
|
|
27
|
-
|
27
|
+
_onClose: ( event ) ->
|
28
28
|
@trigger 'close'
|
29
|
-
setTimeout ( => @open() ), @
|
30
|
-
@
|
29
|
+
setTimeout ( => @open() ), @_reconnectDelay * 100
|
30
|
+
@_reconnectDelay += 1
|
31
31
|
|
32
|
-
|
32
|
+
_onMessage: ( message ) ->
|
33
33
|
@[ message.action ] message
|
34
34
|
|
35
|
-
|
36
|
-
@
|
35
|
+
_send: ( msg ) ->
|
36
|
+
@_dispatcher.send JSON.stringify msg
|
37
37
|
@
|
38
38
|
|
39
|
-
|
40
|
-
clearTimeout @
|
39
|
+
_keepAlive: ->
|
40
|
+
clearTimeout @_keepAliveTimer if @_keepAliveTimer
|
41
41
|
if @Application.keepAliveDelay
|
42
|
-
@
|
43
|
-
@
|
44
|
-
@
|
42
|
+
@_keepAliveTimer = setTimeout =>
|
43
|
+
@_keepAliveTimer = null
|
44
|
+
@_send ping: true
|
45
45
|
, @Application.keepAliveDelay * 1000
|
46
46
|
@
|
47
47
|
|
48
|
-
|
49
|
-
@
|
48
|
+
_pong: ->
|
49
|
+
@_keepAlive()
|
50
50
|
@
|
51
51
|
|
52
|
-
|
53
|
-
@
|
52
|
+
_identification: ->
|
53
|
+
@_send nali_browser_id: @Cookie.get( 'nali_browser_id' ) or @Cookie.set 'nali_browser_id', @Model.guid()
|
54
54
|
@
|
55
55
|
|
56
|
-
|
56
|
+
_sync: ( message ) ->
|
57
57
|
@Model.sync message.params
|
58
58
|
@
|
59
59
|
|
60
|
-
|
60
|
+
_appRun: ( { method, params } ) ->
|
61
61
|
@Application[ method ]? params
|
62
62
|
@
|
63
63
|
|
64
|
-
|
64
|
+
_callMethod: ( { model, method, params } ) ->
|
65
65
|
if model is 'Notice' then @Notice[ method ] params
|
66
66
|
else
|
67
67
|
[ model, id ] = model.split '.'
|
68
68
|
@Model.callStackAdd model: model, id: id, method: method, params: params
|
69
69
|
@
|
70
70
|
|
71
|
-
|
72
|
-
@
|
73
|
-
delete @
|
71
|
+
_success: ( message ) ->
|
72
|
+
@_journal[ message.journal_id ].success? message.params
|
73
|
+
delete @_journal[ message.journal_id ]
|
74
74
|
@
|
75
75
|
|
76
|
-
|
77
|
-
@
|
78
|
-
delete @
|
76
|
+
_failure: ( message ) ->
|
77
|
+
@_journal[ message.journal_id ].failure? message.params
|
78
|
+
delete @_journal[ message.journal_id ]
|
79
79
|
@
|
80
80
|
|
81
81
|
query: ( to, params, success, failure ) ->
|
82
82
|
return success?() unless @Application.useWebSockets
|
83
83
|
[ controller, action ] = to.split '.'
|
84
|
-
@
|
85
|
-
@
|
84
|
+
@_journal.push callbacks = success: success, failure: failure
|
85
|
+
@_send
|
86
86
|
controller: controller
|
87
87
|
action: action
|
88
88
|
params: params
|
89
|
-
journal_id: @
|
89
|
+
journal_id: @_journal.indexOf callbacks
|
90
90
|
@
|
@@ -2,14 +2,14 @@ Nali.extend Controller:
|
|
2
2
|
|
3
3
|
extension: ->
|
4
4
|
if @_name isnt 'Controller'
|
5
|
-
@
|
5
|
+
@_prepareActions()
|
6
6
|
@modelName = @_name.replace /s$/, ''
|
7
7
|
@
|
8
8
|
|
9
9
|
new: ( collection, filters, params ) ->
|
10
10
|
@clone collection: collection, filters: filters, params: params
|
11
11
|
|
12
|
-
|
12
|
+
_prepareActions: ->
|
13
13
|
@_actions = {}
|
14
14
|
for name, action of @actions when not ( name in [ 'default', 'before', 'after' ] )
|
15
15
|
[ name, filters... ] = name.split '/'
|
@@ -18,23 +18,23 @@ Nali.extend Controller:
|
|
18
18
|
filters.splice filters.indexOf( filter ), 1
|
19
19
|
params.push filter[ 1.. ]
|
20
20
|
@_actions[ name ] = filters: filters, params: params, methods: [ action ]
|
21
|
-
@
|
22
|
-
@
|
21
|
+
@_prepareBefores()
|
22
|
+
@_prepareAfters()
|
23
23
|
@
|
24
24
|
|
25
|
-
|
25
|
+
_prepareBefores: ->
|
26
26
|
if @actions?.before?
|
27
|
-
list = @
|
27
|
+
list = @_analizeFilters 'before'
|
28
28
|
@_actions[ name ].methods = actions.concat @_actions[ name ].methods for name, actions of list
|
29
29
|
@
|
30
30
|
|
31
|
-
|
31
|
+
_prepareAfters: ->
|
32
32
|
if @actions?.after?
|
33
|
-
list = @
|
33
|
+
list = @_analizeFilters 'after'
|
34
34
|
@_actions[ name ].methods = @_actions[ name ].methods.concat actions for name, actions of list
|
35
35
|
@
|
36
36
|
|
37
|
-
|
37
|
+
_analizeFilters: ( type ) ->
|
38
38
|
list = {}
|
39
39
|
for names, action of @actions[ type ]
|
40
40
|
[ invert, names ] = switch
|
@@ -51,15 +51,15 @@ Nali.extend Controller:
|
|
51
51
|
@
|
52
52
|
|
53
53
|
runAction: ( name ) ->
|
54
|
-
method.call @ for method in @_actions[ name ].methods when not @
|
55
|
-
if @
|
54
|
+
method.call @ for method in @_actions[ name ].methods when not @_stopped
|
55
|
+
if @_stopped then @collection.destroy()
|
56
56
|
else
|
57
57
|
@collection.show name
|
58
58
|
@Router.changeUrl()
|
59
59
|
@
|
60
60
|
|
61
61
|
stop: ->
|
62
|
-
@
|
62
|
+
@_stopped = true
|
63
63
|
@
|
64
64
|
|
65
65
|
redirect: ( args... ) ->
|
@@ -2,60 +2,59 @@ Nali.extend Model:
|
|
2
2
|
|
3
3
|
extension: ->
|
4
4
|
if @_name isnt 'Model'
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
5
|
+
@_table = @_tables[ @_name ] ?= []
|
6
|
+
@_table.index = {}
|
7
|
+
@_parseRelations()
|
8
|
+
@_adapt()
|
9
9
|
@
|
10
10
|
|
11
11
|
cloning: ->
|
12
|
-
@
|
12
|
+
@_views = {}
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
_tables: {}
|
15
|
+
_callStack: []
|
16
|
+
attributes: {}
|
16
17
|
updated: 0
|
17
|
-
callStack: []
|
18
18
|
destroyed: false
|
19
19
|
|
20
|
-
|
21
|
-
for name, method of @ when /^
|
20
|
+
_adapt: ->
|
21
|
+
for name, method of @ when /^__\w+/.test name
|
22
22
|
do ( name, method ) =>
|
23
|
-
if typeof method is 'function'
|
24
|
-
|
25
|
-
@adaptViews()
|
23
|
+
@[ name[ 2.. ] ] = @[ name ] if typeof method is 'function'
|
24
|
+
@_adaptViews()
|
26
25
|
@
|
27
26
|
|
28
|
-
|
29
|
-
@
|
27
|
+
_adaptViews: ->
|
28
|
+
@_views = {}
|
30
29
|
for name, view of @View.extensions when name.indexOf( @_name ) >= 0
|
31
30
|
do ( name, view ) =>
|
32
|
-
@
|
31
|
+
@_views[ short = view._shortName ] = view
|
33
32
|
shortCap = short.capitalize()
|
34
33
|
unless @[ viewMethod = 'view' + shortCap ]? then @[ viewMethod ] = -> @view short
|
35
34
|
unless @[ showMethod = 'show' + shortCap ]? then @[ showMethod ] = ( insertTo ) -> @show short, insertTo
|
36
35
|
unless @[ hideMethod = 'hide' + shortCap ]? then @[ hideMethod ] = -> @hide short
|
37
36
|
@
|
38
37
|
|
39
|
-
|
38
|
+
_callStackAdd: ( params ) ->
|
40
39
|
# добавляет задачу в очередь на выполнение, запускает выполнение очереди
|
41
|
-
@
|
40
|
+
@_callStack.push params
|
42
41
|
@runStack()
|
43
42
|
@
|
44
43
|
|
45
44
|
runStack: ->
|
46
45
|
# запускает выполнение задач у существующих моделей
|
47
|
-
for item, index in @
|
46
|
+
for item, index in @_callStack[ 0.. ]
|
48
47
|
if model = @extensions[ item.model ].find item.id
|
49
48
|
model[ item.method ] item.params
|
50
|
-
@
|
49
|
+
@_callStack.splice @_callStack.indexOf( item ), 1
|
51
50
|
@
|
52
51
|
|
53
52
|
# работа с моделями
|
54
53
|
|
55
|
-
|
54
|
+
_accessing: ->
|
56
55
|
# устанавливает геттеры доступа к атрибутам и связям
|
57
56
|
@access @attributes
|
58
|
-
@
|
57
|
+
@_setRelations()
|
59
58
|
@
|
60
59
|
|
61
60
|
save: ( success, failure ) ->
|
@@ -70,16 +69,16 @@ Nali.extend Model:
|
|
70
69
|
else failure? @
|
71
70
|
@
|
72
71
|
|
73
|
-
sync: ( {
|
72
|
+
sync: ( { name, attributes, created, updated, destroyed } ) ->
|
74
73
|
# синхронизирует пришедшую с сервера модель с локальной, либо создает новую
|
75
|
-
if model = @extensions[
|
74
|
+
if model = @extensions[ name ].find attributes.id
|
76
75
|
if destroyed then model.remove()
|
77
76
|
else if updated > @updated
|
78
77
|
model.updated = updated
|
79
78
|
model.created = created
|
80
79
|
model.update attributes
|
81
80
|
else
|
82
|
-
model = @extensions[
|
81
|
+
model = @extensions[ name ].new attributes
|
83
82
|
model.updated = updated
|
84
83
|
model.created = created
|
85
84
|
model.write()
|
@@ -98,13 +97,13 @@ Nali.extend Model:
|
|
98
97
|
@
|
99
98
|
|
100
99
|
written: ->
|
101
|
-
@ in @
|
100
|
+
@ in @_table
|
102
101
|
|
103
102
|
write: ->
|
104
103
|
# добавляет модель в локальную таблицу, генерирует событие create
|
105
|
-
@
|
104
|
+
@_table.index[ @id ] = @ if @id and not @_table.index[ @id ]
|
106
105
|
unless @written()
|
107
|
-
@
|
106
|
+
@_table.push @
|
108
107
|
@onCreate?()
|
109
108
|
@Model.trigger "create.#{ @_name.lower() }", @
|
110
109
|
@Model.runStack()
|
@@ -114,8 +113,8 @@ Nali.extend Model:
|
|
114
113
|
# удаляет модель из локальной таблицы, генерирует событие destroy
|
115
114
|
if @written()
|
116
115
|
@destroyed = true
|
117
|
-
delete @
|
118
|
-
@
|
116
|
+
delete @_table.index[ @id ]
|
117
|
+
@_table.splice @_table.indexOf( @ ), 1
|
119
118
|
@trigger 'destroy'
|
120
119
|
@Model.trigger "destroy.#{ @_name.lower() }", @
|
121
120
|
@onDestroy?()
|
@@ -124,8 +123,8 @@ Nali.extend Model:
|
|
124
123
|
|
125
124
|
new: ( attributes ) ->
|
126
125
|
# создает модель, не сохраняя её на сервере
|
127
|
-
model = @clone( attributes: @
|
128
|
-
model[ name ] = @
|
126
|
+
model = @clone( attributes: @_defaultAttributes() )._accessing()
|
127
|
+
model[ name ] = @_normalizeAttributeValue name, value for name, value of attributes
|
129
128
|
model
|
130
129
|
|
131
130
|
create: ( attributes, success, failure ) ->
|
@@ -144,7 +143,7 @@ Nali.extend Model:
|
|
144
143
|
|
145
144
|
updateProperty: ( name, value, checkValidation = true ) ->
|
146
145
|
# обновляет один атрибут модели, проверяя его валидность, генерирует событие update.propertyName
|
147
|
-
value = @
|
146
|
+
value = @_normalizeAttributeValue name, value
|
148
147
|
if @[ name ] isnt value and ( not checkValidation or @isValidAttributeValue( name, value ) )
|
149
148
|
@[ name ] = value
|
150
149
|
@[ 'onUpdate' + name.capitalize() ]?()
|
@@ -166,7 +165,7 @@ Nali.extend Model:
|
|
166
165
|
|
167
166
|
find: ( id ) ->
|
168
167
|
# находит модель по её id используя индекс
|
169
|
-
@
|
168
|
+
@_table.index[ id ]
|
170
169
|
|
171
170
|
where: ( filters ) ->
|
172
171
|
# возвращает коллекцию моделей соответствующих фильтру
|
@@ -178,7 +177,7 @@ Nali.extend Model:
|
|
178
177
|
|
179
178
|
each: ( callback ) ->
|
180
179
|
# применяет колбек ко всем моделям
|
181
|
-
callback.call @, model for model in @
|
180
|
+
callback.call @, model for model in @_table
|
182
181
|
@
|
183
182
|
|
184
183
|
# работа с аттрибутами
|
@@ -191,16 +190,16 @@ Nali.extend Model:
|
|
191
190
|
date = Math.floor date / 16
|
192
191
|
( if sub is 'x' then rand else ( rand & 0x7 | 0x8 ) ).toString 16
|
193
192
|
|
194
|
-
|
193
|
+
_defaultAttributes: ->
|
195
194
|
# возвращает объект аттрибутов по умолчанию
|
196
195
|
attributes = id: @guid()
|
197
196
|
for name, value of @attributes
|
198
197
|
if value instanceof Object
|
199
|
-
attributes[ name ] = if value.default? then @
|
200
|
-
else attributes[ name ] = @
|
198
|
+
attributes[ name ] = if value.default? then @_normalizeAttributeValue name, value.default else null
|
199
|
+
else attributes[ name ] = @_normalizeAttributeValue name, value
|
201
200
|
attributes
|
202
201
|
|
203
|
-
|
202
|
+
_normalizeAttributeValue: ( name, value ) ->
|
204
203
|
# если формат свойства number пробует привести значение к числу
|
205
204
|
if @::attributes[ name ]?.format is 'number' and value is ( ( correct = + value ) + '' ) then correct else value
|
206
205
|
|
@@ -232,17 +231,17 @@ Nali.extend Model:
|
|
232
231
|
|
233
232
|
# работа со связями
|
234
233
|
|
235
|
-
|
234
|
+
_parseRelations: ( type, options ) ->
|
236
235
|
# производит разбор связей
|
237
236
|
@relations = {}
|
238
237
|
for type in [ 'belongsTo', 'hasOne', 'hasMany' ]
|
239
238
|
for options in [].concat( @[ type ] ) when @[ type ]?
|
240
|
-
params = @[ '
|
239
|
+
params = @[ '_parse' + type.capitalize() ] @_parseInitialRelationParams options
|
241
240
|
section = type + if params.through? then 'Through' else ''
|
242
241
|
( @relations[ section ] ?= [] ).push params
|
243
242
|
@
|
244
243
|
|
245
|
-
|
244
|
+
_parseInitialRelationParams: ( options ) ->
|
246
245
|
# дает начальные параметры настроек связи
|
247
246
|
if typeof options is 'object'
|
248
247
|
params = name: Object.keys( options )[0]
|
@@ -253,41 +252,41 @@ Nali.extend Model:
|
|
253
252
|
params = name: options
|
254
253
|
params
|
255
254
|
|
256
|
-
|
255
|
+
_parseBelongsTo: ( params ) ->
|
257
256
|
# производит разбор связей belongsTo
|
258
257
|
params.model ?= @Model.extensions[ params.name.capitalize() ]
|
259
258
|
params.key ?= params.name.lower() + '_id'
|
260
259
|
params
|
261
260
|
|
262
|
-
|
261
|
+
_parseHasOne: ( params ) ->
|
263
262
|
# производит разбор связей hasOne
|
264
263
|
params.model ?= @Model.extensions[ params.name.capitalize() ]
|
265
264
|
params.key ?= ( if params.through then params.name else @_name + '_id' ).lower()
|
266
265
|
params
|
267
266
|
|
268
|
-
|
267
|
+
_parseHasMany: ( params ) ->
|
269
268
|
# производит разбор связей hasMany
|
270
269
|
params.model ?= @Model.extensions[ params.name[ ...-1 ].capitalize() ]
|
271
270
|
params.key ?= ( if params.through then params.name[ ...-1 ] else @_name + '_id' ).lower()
|
272
271
|
params
|
273
272
|
|
274
|
-
|
273
|
+
_setRelations: ->
|
275
274
|
# запускает установку связей у модели
|
276
|
-
@
|
275
|
+
@_setRelationsType type for type in [ 'belongsTo', 'hasOne', 'hasMany', 'hasOneThrough', 'hasManyThrough' ]
|
277
276
|
@
|
278
277
|
|
279
|
-
|
278
|
+
_setRelationsType: ( type ) ->
|
280
279
|
# запускает установку связей определенного типа
|
281
280
|
if params = @relations[ type ]
|
282
|
-
@[ '
|
281
|
+
@[ '_set' + type.capitalize() ] param for param in params
|
283
282
|
@
|
284
283
|
|
285
|
-
|
284
|
+
_setBelongsTo: ( { key, model, name, through } ) ->
|
286
285
|
# устанавливает геттер типа belongsTo возвращающий связанную модель
|
287
286
|
@getter name, => model.find @[ key ]
|
288
287
|
@
|
289
288
|
|
290
|
-
|
289
|
+
_setHasOne: ( { key, model, name, through } ) ->
|
291
290
|
# устанавливает геттер типа hasOne возвращающий связанную модель
|
292
291
|
@getter name, =>
|
293
292
|
delete @[ name ]
|
@@ -297,7 +296,7 @@ Nali.extend Model:
|
|
297
296
|
@[ name ]
|
298
297
|
@
|
299
298
|
|
300
|
-
|
299
|
+
_setHasMany: ( { key, model, name, through } ) ->
|
301
300
|
# устанавливает геттер типа hasMany возвращающий коллекцию связанных моделей
|
302
301
|
@getter name, =>
|
303
302
|
delete @[ name ]
|
@@ -305,7 +304,7 @@ Nali.extend Model:
|
|
305
304
|
@[ name ] = model.where filters
|
306
305
|
@
|
307
306
|
|
308
|
-
|
307
|
+
_setHasOneThrough: ( { key, model, name, through } ) ->
|
309
308
|
# устанавливает геттер типа hasOne возвращающий модель,
|
310
309
|
# связанную с текущей через модель through
|
311
310
|
@getter name, =>
|
@@ -314,7 +313,7 @@ Nali.extend Model:
|
|
314
313
|
@[ name ]
|
315
314
|
@
|
316
315
|
|
317
|
-
|
316
|
+
_setHasManyThrough: ( { key, model, name, through } ) ->
|
318
317
|
# устанавливает геттер типа hasMany возвращающий коллекцию моделей,
|
319
318
|
# связанных с текущей через модель through
|
320
319
|
@getter name, =>
|
@@ -332,9 +331,9 @@ Nali.extend Model:
|
|
332
331
|
|
333
332
|
view: ( name ) ->
|
334
333
|
# возвращает объект вида, либо новый, либо ранее созданный
|
335
|
-
unless ( view = @
|
336
|
-
if ( view = @::
|
337
|
-
view = @
|
334
|
+
unless ( view = @_views[ name ] )?
|
335
|
+
if ( view = @::_views[ name ] )?
|
336
|
+
view = @_views[ name ] = view.clone model: @
|
338
337
|
else console.error 'View "%s" of model "%s" does not exist', name, @_name
|
339
338
|
view
|
340
339
|
|