nali 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|