volt 0.6.5 → 0.7.0
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.
- checksums.yaml +4 -4
- data/Readme.md +47 -40
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +3 -3
- data/app/volt/tasks/live_query/data_store.rb +2 -2
- data/app/volt/tasks/live_query/live_query.rb +20 -20
- data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
- data/app/volt/tasks/live_query/query_tracker.rb +15 -15
- data/app/volt/tasks/query_tasks.rb +13 -13
- data/app/volt/tasks/store_tasks.rb +7 -7
- data/app/volt/views/notices/index.html +17 -18
- data/lib/volt/assets/test.rb +2 -2
- data/lib/volt/benchmark/benchmark.rb +25 -23
- data/lib/volt/cli/asset_compile.rb +11 -0
- data/lib/volt/cli/new_gem.rb +16 -16
- data/lib/volt/cli.rb +14 -12
- data/lib/volt/console.rb +5 -6
- data/lib/volt/controllers/model_controller.rb +18 -18
- data/lib/volt/extra_core/array.rb +4 -4
- data/lib/volt/extra_core/hash.rb +3 -3
- data/lib/volt/extra_core/object.rb +6 -6
- data/lib/volt/extra_core/string.rb +6 -6
- data/lib/volt/extra_core/symbol.rb +5 -5
- data/lib/volt/extra_core/time.rb +4 -4
- data/lib/volt/extra_core/true_false.rb +6 -6
- data/lib/volt/extra_core/try.rb +9 -9
- data/lib/volt/models/array_model.rb +26 -26
- data/lib/volt/models/model.rb +35 -35
- data/lib/volt/models/model_hash_behaviour.rb +15 -15
- data/lib/volt/models/model_helpers.rb +8 -8
- data/lib/volt/models/model_wrapper.rb +6 -6
- data/lib/volt/models/persistors/array_store.rb +36 -36
- data/lib/volt/models/persistors/base.rb +6 -6
- data/lib/volt/models/persistors/flash.rb +5 -5
- data/lib/volt/models/persistors/model_identity_map.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +22 -22
- data/lib/volt/models/persistors/params.rb +3 -3
- data/lib/volt/models/persistors/query/query_listener.rb +14 -14
- data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
- data/lib/volt/models/persistors/store.rb +8 -8
- data/lib/volt/models/persistors/store_factory.rb +2 -2
- data/lib/volt/models/url.rb +37 -37
- data/lib/volt/page/bindings/attribute_binding.rb +14 -14
- data/lib/volt/page/bindings/base_binding.rb +9 -9
- data/lib/volt/page/bindings/component_binding.rb +7 -7
- data/lib/volt/page/bindings/content_binding.rb +3 -3
- data/lib/volt/page/bindings/each_binding.rb +13 -13
- data/lib/volt/page/bindings/event_binding.rb +4 -4
- data/lib/volt/page/bindings/if_binding.rb +12 -12
- data/lib/volt/page/bindings/template_binding.rb +30 -30
- data/lib/volt/page/channel.rb +19 -19
- data/lib/volt/page/channel_stub.rb +6 -6
- data/lib/volt/page/document.rb +2 -2
- data/lib/volt/page/document_events.rb +4 -4
- data/lib/volt/page/draw_cycle.rb +3 -3
- data/lib/volt/page/memory_test.rb +6 -6
- data/lib/volt/page/page.rb +19 -19
- data/lib/volt/page/reactive_template.rb +9 -9
- data/lib/volt/page/sub_context.rb +5 -5
- data/lib/volt/page/targets/attribute_section.rb +9 -9
- data/lib/volt/page/targets/attribute_target.rb +3 -3
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
- data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
- data/lib/volt/page/targets/dom_section.rb +40 -38
- data/lib/volt/page/targets/dom_target.rb +2 -2
- data/lib/volt/page/tasks.rb +12 -12
- data/lib/volt/page/template_renderer.rb +4 -4
- data/lib/volt/page/url_tracker.rb +6 -6
- data/lib/volt/reactive/array_extensions.rb +2 -2
- data/lib/volt/reactive/destructive_methods.rb +5 -5
- data/lib/volt/reactive/event_chain.rb +25 -25
- data/lib/volt/reactive/events.rb +33 -33
- data/lib/volt/reactive/object_tracker.rb +21 -21
- data/lib/volt/reactive/object_tracking.rb +2 -2
- data/lib/volt/reactive/reactive_array.rb +57 -57
- data/lib/volt/reactive/reactive_tags.rb +16 -16
- data/lib/volt/reactive/reactive_value.rb +72 -72
- data/lib/volt/reactive/string_extensions.rb +3 -3
- data/lib/volt/router/routes.rb +22 -23
- data/lib/volt/server/component_handler.rb +5 -5
- data/lib/volt/server/component_templates.rb +14 -11
- data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
- data/lib/volt/server/html_parser/each_scope.rb +18 -0
- data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
- data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
- data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
- data/lib/volt/server/html_parser/view_handler.rb +82 -0
- data/lib/volt/server/html_parser/view_parser.rb +23 -0
- data/lib/volt/server/html_parser/view_scope.rb +145 -0
- data/lib/volt/server/rack/asset_files.rb +17 -17
- data/lib/volt/server/rack/component_paths.rb +18 -18
- data/lib/volt/server/rack/index_files.rb +8 -8
- data/lib/volt/server/rack/opal_files.rb +11 -11
- data/lib/volt/server/socket_connection_handler.rb +13 -13
- data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
- data/lib/volt/server.rb +18 -18
- data/lib/volt/tasks/dispatcher.rb +5 -5
- data/lib/volt/utils/ejson.rb +2 -2
- data/lib/volt/utils/generic_counting_pool.rb +8 -8
- data/lib/volt/utils/generic_pool.rb +16 -16
- data/lib/volt/volt/environment.rb +4 -4
- data/lib/volt.rb +6 -6
- data/spec/integration/test_integration_spec.rb +2 -2
- data/spec/models/event_chain_spec.rb +38 -38
- data/spec/models/model_spec.rb +128 -128
- data/spec/models/old_model_spec.rb +17 -17
- data/spec/models/persistors/params_spec.rb +3 -3
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/reactive_array_spec.rb +82 -82
- data/spec/models/reactive_generator_spec.rb +11 -11
- data/spec/models/reactive_tags_spec.rb +6 -6
- data/spec/models/reactive_value_spec.rb +70 -70
- data/spec/models/store_spec.rb +4 -4
- data/spec/models/string_extensions_spec.rb +13 -13
- data/spec/page/bindings/content_binding_spec.rb +6 -6
- data/spec/page/sub_context_spec.rb +1 -1
- data/spec/router/routes_spec.rb +3 -3
- data/spec/server/html_parser/sample_page.html +595 -0
- data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
- data/spec/server/html_parser/view_parser_spec.rb +286 -0
- data/spec/server/rack/asset_files_spec.rb +6 -6
- data/spec/server/rack/component_paths_spec.rb +5 -5
- data/spec/spec_helper.rb +4 -5
- data/spec/store/mongo_spec.rb +3 -3
- data/spec/tasks/live_query_spec.rb +6 -6
- data/spec/tasks/query_tasks.rb +4 -4
- data/spec/tasks/query_tracker_spec.rb +20 -20
- data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
- data/spec/templates/template_binding_spec.rb +28 -28
- data/spec/utils/generic_counting_pool_spec.rb +5 -5
- data/spec/utils/generic_pool_spec.rb +14 -14
- data/templates/newgem/app/newgem/views/index/index.html +1 -2
- data/templates/project/app/home/config/dependencies.rb +1 -1
- data/templates/project/app/home/controllers/index_controller.rb +1 -1
- data/templates/project/app/home/views/index/about.html +4 -6
- data/templates/project/app/home/views/index/home.html +4 -5
- data/templates/project/app/home/views/index/index.html +8 -9
- data/templates/project/spec/spec_helper.rb +1 -1
- metadata +17 -8
- data/lib/volt/server/binding_setup.rb +0 -2
- data/lib/volt/server/if_binding_setup.rb +0 -31
- data/lib/volt/server/scope.rb +0 -43
- data/lib/volt/server/template_parser.rb +0 -453
- data/spec/server/template_parser_spec.rb +0 -50
|
@@ -4,7 +4,7 @@ require 'volt/models/model_helpers'
|
|
|
4
4
|
class ArrayModel < ReactiveArray
|
|
5
5
|
include ModelWrapper
|
|
6
6
|
include ModelHelpers
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
attr_reader :parent, :path, :persistor, :options
|
|
9
9
|
|
|
10
10
|
def initialize(array=[], options={})
|
|
@@ -12,26 +12,26 @@ class ArrayModel < ReactiveArray
|
|
|
12
12
|
@parent = options[:parent]
|
|
13
13
|
@path = options[:path] || []
|
|
14
14
|
@persistor = setup_persistor(options[:persistor])
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
array = wrap_values(array)
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
super(array)
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
@persistor.loaded if @persistor
|
|
21
21
|
end
|
|
22
|
-
|
|
23
|
-
# For stored items, tell the collection to load the data when it
|
|
22
|
+
|
|
23
|
+
# For stored items, tell the collection to load the data when it
|
|
24
24
|
# is requested.
|
|
25
25
|
def [](index)
|
|
26
26
|
load_data
|
|
27
27
|
super
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
def size
|
|
31
31
|
load_data
|
|
32
32
|
super
|
|
33
33
|
end
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
def state
|
|
36
36
|
if @persistor
|
|
37
37
|
@persistor.state
|
|
@@ -39,11 +39,11 @@ class ArrayModel < ReactiveArray
|
|
|
39
39
|
:loaded
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def loaded?
|
|
44
44
|
state == :loaded
|
|
45
45
|
end
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
tag_method(:find) do
|
|
48
48
|
destructive!
|
|
49
49
|
pass_reactive!
|
|
@@ -55,11 +55,11 @@ class ArrayModel < ReactiveArray
|
|
|
55
55
|
raise "this model's persistance layer does not support find, try using store"
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
def attributes
|
|
60
60
|
self
|
|
61
61
|
end
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
# Make sure it gets wrapped
|
|
64
64
|
def <<(model)
|
|
65
65
|
if model.cur.is_a?(Model)
|
|
@@ -68,12 +68,12 @@ class ArrayModel < ReactiveArray
|
|
|
68
68
|
else
|
|
69
69
|
model = wrap_values([model]).first
|
|
70
70
|
end
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
super(model)
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
@persistor.added(model, @array.size-1) if @persistor
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
# Make sure it gets wrapped
|
|
78
78
|
def inject(*args)
|
|
79
79
|
args = wrap_values(args)
|
|
@@ -89,21 +89,21 @@ class ArrayModel < ReactiveArray
|
|
|
89
89
|
def new_model(attributes, options)
|
|
90
90
|
class_at_path(options[:path]).new(attributes, options)
|
|
91
91
|
end
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
def new_array_model(*args)
|
|
94
94
|
ArrayModel.new(*args)
|
|
95
95
|
end
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
# Convert the model to an array all of the way down
|
|
98
98
|
def to_a
|
|
99
99
|
array = []
|
|
100
|
-
attributes.each do |value|
|
|
100
|
+
attributes.each do |value|
|
|
101
101
|
array << deep_unwrap(value)
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
return array
|
|
105
105
|
end
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
def inspect
|
|
108
108
|
if @persistor && @persistor.is_a?(Persistors::ArrayStore) && state == :not_loaded
|
|
109
109
|
# Show a special message letting users know it is not loaded yet.
|
|
@@ -113,8 +113,8 @@ class ArrayModel < ReactiveArray
|
|
|
113
113
|
# Otherwise inspect normally
|
|
114
114
|
super
|
|
115
115
|
end
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
|
|
117
|
+
|
|
118
118
|
private
|
|
119
119
|
# Takes the persistor if there is one and
|
|
120
120
|
def setup_persistor(persistor)
|
|
@@ -122,13 +122,13 @@ class ArrayModel < ReactiveArray
|
|
|
122
122
|
@persistor = persistor.new(self)
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
# Loads data in an array store persistor when data is requested.
|
|
127
127
|
def load_data
|
|
128
128
|
if @persistor && @persistor.is_a?(Persistors::ArrayStore)
|
|
129
129
|
@persistor.load_data
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
end
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
end
|
data/lib/volt/models/model.rb
CHANGED
|
@@ -8,7 +8,7 @@ class NilMethodCall < NoMethodError
|
|
|
8
8
|
def true?
|
|
9
9
|
false
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def false?
|
|
13
13
|
true
|
|
14
14
|
end
|
|
@@ -20,18 +20,18 @@ class Model
|
|
|
20
20
|
include ObjectTracking
|
|
21
21
|
include ModelHelpers
|
|
22
22
|
include ModelHashBehaviour
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
attr_accessor :attributes
|
|
25
25
|
attr_reader :parent, :path, :persistor, :options
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
def initialize(attributes={}, options={})
|
|
28
28
|
self.options = options
|
|
29
29
|
|
|
30
30
|
self.attributes = wrap_values(attributes)
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
@persistor.loaded if @persistor
|
|
33
33
|
end
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
# Update the options
|
|
36
36
|
def options=(options)
|
|
37
37
|
@options = options
|
|
@@ -40,8 +40,8 @@ class Model
|
|
|
40
40
|
@class_paths = options[:class_paths]
|
|
41
41
|
@persistor = setup_persistor(options[:persistor])
|
|
42
42
|
end
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
|
|
45
45
|
# Pass the comparison through
|
|
46
46
|
def ==(val)
|
|
47
47
|
if val.is_a?(Model)
|
|
@@ -52,13 +52,13 @@ class Model
|
|
|
52
52
|
return attributes == val
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
# Pass through needed
|
|
57
57
|
def !
|
|
58
58
|
!attributes
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
tag_all_methods do
|
|
63
63
|
pass_reactive! do |method_name|
|
|
64
64
|
method_name[0] == '_' && method_name[-1] == '='
|
|
@@ -78,23 +78,23 @@ class Model
|
|
|
78
78
|
attributes.send(method_name, *args, &block)
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
# Do the assignment to a model and trigger a changed event
|
|
83
83
|
def assign_attribute(method_name, *args, &block)
|
|
84
84
|
self.expand!
|
|
85
85
|
# Assign, without the =
|
|
86
86
|
attribute_name = method_name[0..-2].to_sym
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
value = args[0]
|
|
89
89
|
__assign_element(attribute_name, value)
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
attributes[attribute_name] = wrap_value(value, [attribute_name])
|
|
92
92
|
trigger_by_attribute!('changed', attribute_name)
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# Let the persistor know something changed
|
|
95
95
|
@persistor.changed(attribute_name) if @persistor
|
|
96
96
|
end
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
# When reading an attribute, we need to handle reading on:
|
|
99
99
|
# 1) a nil model, which returns a wrapped error
|
|
100
100
|
# 2) reading directly from attributes
|
|
@@ -102,9 +102,9 @@ class Model
|
|
|
102
102
|
def read_attribute(method_name)
|
|
103
103
|
# Reading an attribute, we may get back a nil model.
|
|
104
104
|
method_name = method_name.to_sym
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
if method_name[0] != '_' && attributes == nil
|
|
107
|
-
# The method we are calling is on a nil model, return a wrapped
|
|
107
|
+
# The method we are calling is on a nil model, return a wrapped
|
|
108
108
|
# exception.
|
|
109
109
|
return return_undefined_method(method_name)
|
|
110
110
|
elsif attributes && attributes.has_key?(method_name)
|
|
@@ -123,7 +123,7 @@ class Model
|
|
|
123
123
|
return new_model(nil, @options.merge(parent: self, path: path + [method_name]))
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
def return_undefined_method(method_name)
|
|
128
128
|
# Methods called on nil capture an error so the user can know where
|
|
129
129
|
# their nil calls are. This error can be re-raised at a later point.
|
|
@@ -137,28 +137,28 @@ class Model
|
|
|
137
137
|
result.backtrace.reject! {|line| line['lib/models/model.rb'] || line['lib/models/live_value.rb'] }
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
def new_model(attributes, options)
|
|
142
142
|
class_at_path(options[:path]).new(attributes, options)
|
|
143
143
|
end
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
def new_array_model(*args)
|
|
146
146
|
ArrayModel.new(*args)
|
|
147
147
|
end
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
def trigger_by_attribute!(event_name, attribute, *passed_args)
|
|
150
150
|
trigger_by_scope!(event_name, *passed_args) do |scope|
|
|
151
151
|
method_name, *args, block = scope
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
# TODO: Opal bug
|
|
154
154
|
args ||= []
|
|
155
|
-
|
|
155
|
+
|
|
156
156
|
# Any methods without _ are not directly related to one attribute, so
|
|
157
157
|
# they should all trigger
|
|
158
158
|
!method_name || method_name[0] != '_' || (method_name == attribute.to_sym && args.size == 0)
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
# If this model is nil, it makes it into a hash model, then
|
|
163
163
|
# sets it up to track from the parent.
|
|
164
164
|
def expand!
|
|
@@ -166,12 +166,12 @@ class Model
|
|
|
166
166
|
self.attributes = {}
|
|
167
167
|
if @parent
|
|
168
168
|
@parent.expand!
|
|
169
|
-
|
|
169
|
+
|
|
170
170
|
@parent.attributes[@path.last] = self
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
end
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
tag_method(:<<) do
|
|
176
176
|
pass_reactive!
|
|
177
177
|
end
|
|
@@ -186,7 +186,7 @@ class Model
|
|
|
186
186
|
# Grab the last section of the path, so we can do the assign on the parent
|
|
187
187
|
path = @path.last
|
|
188
188
|
result = @parent.send(path)
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
if result.nil?
|
|
191
191
|
# If this isn't a model yet, instantiate it
|
|
192
192
|
@parent.send(:"#{path}=", new_array_model([], @options))
|
|
@@ -195,47 +195,47 @@ class Model
|
|
|
195
195
|
|
|
196
196
|
# Add the new item
|
|
197
197
|
result << value
|
|
198
|
-
|
|
198
|
+
|
|
199
199
|
return nil
|
|
200
200
|
end
|
|
201
|
-
|
|
201
|
+
|
|
202
202
|
def inspect
|
|
203
203
|
"<#{self.class.to_s} #{attributes.inspect}>"
|
|
204
204
|
end
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
def deep_cur
|
|
207
207
|
attributes
|
|
208
208
|
end
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
private
|
|
211
211
|
# Clear the previous value and assign a new one
|
|
212
212
|
def __assign_element(key, value)
|
|
213
213
|
__clear_element(key)
|
|
214
214
|
__track_element(key, value)
|
|
215
215
|
end
|
|
216
|
-
|
|
216
|
+
|
|
217
217
|
# TODO: Somewhat duplicated from ReactiveArray
|
|
218
218
|
def __clear_element(key)
|
|
219
219
|
# Cleanup any tracking on an index
|
|
220
220
|
# TODO: is this send a security risk?
|
|
221
221
|
# puts "TRY TO CLEAR: #{key} - #{@reactive_element_listeners && @reactive_element_listeners.keys.inspect}"
|
|
222
|
-
if @reactive_element_listeners && @reactive_element_listeners[key]
|
|
222
|
+
if @reactive_element_listeners && @reactive_element_listeners[key]
|
|
223
223
|
@reactive_element_listeners[key].remove
|
|
224
224
|
@reactive_element_listeners.delete(key)
|
|
225
225
|
end
|
|
226
226
|
end
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
def __track_element(key, value)
|
|
229
229
|
__setup_tracking(key, value) do |event, key, args|
|
|
230
230
|
trigger_by_attribute!(event, key, *args)
|
|
231
231
|
end
|
|
232
232
|
end
|
|
233
|
-
|
|
233
|
+
|
|
234
234
|
# Takes the persistor if there is one and
|
|
235
235
|
def setup_persistor(persistor)
|
|
236
236
|
if persistor
|
|
237
237
|
@persistor = persistor.new(self)
|
|
238
238
|
end
|
|
239
239
|
end
|
|
240
|
-
|
|
240
|
+
|
|
241
241
|
end
|
|
@@ -8,54 +8,54 @@ module ModelHashBehaviour
|
|
|
8
8
|
base.tag_method(:delete) do
|
|
9
9
|
destructive!
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
base.tag_method(:clear) do
|
|
13
13
|
destructive!
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
|
|
18
18
|
def nil?
|
|
19
19
|
attributes.nil?
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
def false?
|
|
23
23
|
attributes.false?
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
def true?
|
|
27
27
|
attributes.true?
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
def delete(*args)
|
|
31
31
|
__clear_element(args[0])
|
|
32
32
|
attributes.delete(*args)
|
|
33
33
|
trigger_by_attribute!('changed', args[0])
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
@persistor.removed(args[0]) if @persistor
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
|
|
39
39
|
def clear
|
|
40
40
|
attributes.each_pair do |key,value|
|
|
41
|
-
__clear_element(key)
|
|
41
|
+
__clear_element(key)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
attributes.clear
|
|
45
45
|
trigger!('changed')
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
@persistor.removed(nil) if @persistor
|
|
48
48
|
end
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
|
|
50
|
+
|
|
51
51
|
# Convert the model to a hash all of the way down.
|
|
52
52
|
def to_h
|
|
53
53
|
hash = {}
|
|
54
54
|
attributes.each_pair do |key, value|
|
|
55
55
|
hash[key] = deep_unwrap(value)
|
|
56
56
|
end
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
return hash
|
|
59
59
|
end
|
|
60
|
-
|
|
61
|
-
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -7,30 +7,30 @@ module ModelHelpers
|
|
|
7
7
|
elsif value.is_a?(ArrayModel)
|
|
8
8
|
value = value.to_a
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
return value
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
# Pass to the persisotr
|
|
15
15
|
def event_added(event, scope_provider, first)
|
|
16
16
|
@persistor.event_added(event, scope_provider, first) if @persistor
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
# Pass to the persistor
|
|
20
20
|
def event_removed(event, no_more_events)
|
|
21
21
|
@persistor.event_removed(event, no_more_events) if @persistor
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Gets the class for a model at the specified path.
|
|
25
25
|
def class_at_path(path)
|
|
26
26
|
if path && path.last == :[]
|
|
27
27
|
begin
|
|
28
28
|
# TODO: SECURITY on the back-end we need to check that the model class we're loading
|
|
29
29
|
# is coming from the models folder.
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
# remove the _ and then singularize
|
|
32
32
|
klass_name = path[-2][1..-1].singularize.camelize
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
klass_name = klass_name.camelize
|
|
35
35
|
klass = Object.send(:const_get, klass_name.to_sym)
|
|
36
36
|
rescue NameError => e
|
|
@@ -40,7 +40,7 @@ module ModelHelpers
|
|
|
40
40
|
else
|
|
41
41
|
klass = Model
|
|
42
42
|
end
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
return klass
|
|
45
45
|
end
|
|
46
|
-
end
|
|
46
|
+
end
|
|
@@ -7,10 +7,10 @@ module ModelWrapper
|
|
|
7
7
|
elsif value.cur.is_a?(Hash)
|
|
8
8
|
value = new_model(value, @options.merge(parent: self, path: path + lookup))
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
return value
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def wrap_values(values, lookup=[])
|
|
15
15
|
if values.cur.is_a?(Array)
|
|
16
16
|
# Coming from an array
|
|
@@ -18,13 +18,13 @@ module ModelWrapper
|
|
|
18
18
|
elsif values.cur.is_a?(Hash)
|
|
19
19
|
pairs = values.map do |k,v|
|
|
20
20
|
path = lookup + [k]
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
[k, wrap_value(v,path)]
|
|
23
23
|
end
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
values = Hash[pairs]
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
return values
|
|
29
29
|
end
|
|
30
|
-
end
|
|
30
|
+
end
|
|
@@ -4,39 +4,39 @@ require 'volt/models/persistors/query/query_listener_pool'
|
|
|
4
4
|
module Persistors
|
|
5
5
|
class ArrayStore < Store
|
|
6
6
|
@@query_pool = QueryListenerPool.new
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
attr_reader :model
|
|
9
9
|
attr_accessor :state
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def self.query_pool
|
|
12
12
|
@@query_pool
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def initialize(model, tasks=nil)
|
|
16
16
|
super
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
@query = ReactiveValue.from_hash(@model.options[:query] || {})
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
# Called when a collection loads
|
|
23
23
|
def loaded
|
|
24
24
|
change_state_to :not_loaded
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
def event_added(event, scope_provider, first)
|
|
28
28
|
puts "ADD EV: #{event} - #{first}"
|
|
29
29
|
# First event, we load the data.
|
|
30
30
|
load_data if first
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def event_removed(event, no_more_events)
|
|
34
34
|
# Remove listener where there are no more events on this model
|
|
35
35
|
if no_more_events && @query_listener && @model.listeners.size == 0
|
|
36
36
|
stop_listening
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
# Called when an event is removed and we no longer want to keep in
|
|
41
41
|
# sync with the database.
|
|
42
42
|
def stop_listening
|
|
@@ -49,7 +49,7 @@ module Persistors
|
|
|
49
49
|
# Called from the QueryListener when the data is loaded
|
|
50
50
|
def change_state_to(new_state)
|
|
51
51
|
@state = new_state
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
# Trigger changed on the 'state' method
|
|
54
54
|
@model.trigger_for_methods!('changed', :state, :loaded?)
|
|
55
55
|
end
|
|
@@ -60,13 +60,13 @@ module Persistors
|
|
|
60
60
|
if @state == :not_loaded || @state == :dirty
|
|
61
61
|
puts "Load Data"
|
|
62
62
|
change_state_to :loading
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
@query_changed_listener.remove if @query_changed_listener
|
|
65
65
|
if @query.reactive?
|
|
66
66
|
# Query might change, change the query when it does
|
|
67
67
|
@query_changed_listener = @query.on('changed') do
|
|
68
68
|
stop_listening
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
load_data
|
|
71
71
|
end
|
|
72
72
|
end
|
|
@@ -74,21 +74,21 @@ module Persistors
|
|
|
74
74
|
run_query(@model, @query.deep_cur)
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
# Clear out the models data, since we're not listening anymore.
|
|
79
79
|
def unload_data
|
|
80
80
|
change_state_to :not_loaded
|
|
81
81
|
@model.clear
|
|
82
82
|
end
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
def run_query(model, query={})
|
|
85
85
|
collection = model.path.last
|
|
86
86
|
# Scope to the parent
|
|
87
87
|
if model.path.size > 1
|
|
88
88
|
parent = model.parent
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
parent.persistor.ensure_setup if parent.persistor
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
if parent && (attrs = parent.attributes) && attrs[:_id].true?
|
|
93
93
|
query[:"#{model.path[-3].singularize}_id"] = attrs[:_id]
|
|
94
94
|
end
|
|
@@ -100,32 +100,32 @@ module Persistors
|
|
|
100
100
|
end
|
|
101
101
|
@query_listener.add_store(model.persistor)
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
def find(query={})
|
|
105
105
|
model = ArrayModel.new([], @model.options.merge(:query => query))
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
return ReactiveValue.new(model)
|
|
108
108
|
end
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
# Called from backend
|
|
111
111
|
def add(index, data)
|
|
112
112
|
$loading_models = true
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
new_options = @model.options.merge(path: @model.path + [:[]], parent: @model)
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
# Find the existing model, or create one
|
|
117
117
|
new_model = @@identity_map.find(data['_id']) { Model.new(data.symbolize_keys, new_options) }
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
@model.insert(index, new_model)
|
|
120
|
-
|
|
121
|
-
$loading_models = false
|
|
120
|
+
|
|
121
|
+
$loading_models = false
|
|
122
122
|
end
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
def remove(ids)
|
|
125
125
|
$loading_models = true
|
|
126
126
|
ids.each do |id|
|
|
127
127
|
puts "delete at: #{id} on #{@model.inspect}"
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
# TODO: optimize this delete so we don't need to loop
|
|
130
130
|
@model.each_with_index do |model, index|
|
|
131
131
|
puts "#{model._id.inspect} vs #{id.inspect} - #{index}"
|
|
@@ -136,34 +136,34 @@ module Persistors
|
|
|
136
136
|
end
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
$loading_models = false
|
|
141
141
|
end
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
def channel_name
|
|
144
144
|
@model.path[-1]
|
|
145
145
|
end
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
|
|
147
|
+
|
|
148
148
|
# When a model is added to this collection, we call its "changed"
|
|
149
149
|
# method. This should trigger a save.
|
|
150
150
|
def added(model, index)
|
|
151
151
|
unless defined?($loading_models) && $loading_models
|
|
152
152
|
model.persistor.changed
|
|
153
153
|
end
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
if model.persistor
|
|
156
156
|
# Tell the persistor it was added
|
|
157
157
|
model.persistor.add_to_collection
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
|
-
|
|
161
|
-
def removed(model)
|
|
160
|
+
|
|
161
|
+
def removed(model)
|
|
162
162
|
if model.persistor
|
|
163
163
|
# Tell the persistor it was removed
|
|
164
164
|
model.persistor.remove_from_collection
|
|
165
165
|
end
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
if $loading_models
|
|
168
168
|
return
|
|
169
169
|
else
|
|
@@ -171,6 +171,6 @@ module Persistors
|
|
|
171
171
|
@tasks.call('StoreTasks', 'delete', channel_name, model.attributes[:_id])
|
|
172
172
|
end
|
|
173
173
|
end
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
end
|
|
176
|
-
end
|
|
176
|
+
end
|