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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/Readme.md +47 -40
  3. data/VERSION +1 -1
  4. data/app/volt/controllers/notices_controller.rb +3 -3
  5. data/app/volt/tasks/live_query/data_store.rb +2 -2
  6. data/app/volt/tasks/live_query/live_query.rb +20 -20
  7. data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
  8. data/app/volt/tasks/live_query/query_tracker.rb +15 -15
  9. data/app/volt/tasks/query_tasks.rb +13 -13
  10. data/app/volt/tasks/store_tasks.rb +7 -7
  11. data/app/volt/views/notices/index.html +17 -18
  12. data/lib/volt/assets/test.rb +2 -2
  13. data/lib/volt/benchmark/benchmark.rb +25 -23
  14. data/lib/volt/cli/asset_compile.rb +11 -0
  15. data/lib/volt/cli/new_gem.rb +16 -16
  16. data/lib/volt/cli.rb +14 -12
  17. data/lib/volt/console.rb +5 -6
  18. data/lib/volt/controllers/model_controller.rb +18 -18
  19. data/lib/volt/extra_core/array.rb +4 -4
  20. data/lib/volt/extra_core/hash.rb +3 -3
  21. data/lib/volt/extra_core/object.rb +6 -6
  22. data/lib/volt/extra_core/string.rb +6 -6
  23. data/lib/volt/extra_core/symbol.rb +5 -5
  24. data/lib/volt/extra_core/time.rb +4 -4
  25. data/lib/volt/extra_core/true_false.rb +6 -6
  26. data/lib/volt/extra_core/try.rb +9 -9
  27. data/lib/volt/models/array_model.rb +26 -26
  28. data/lib/volt/models/model.rb +35 -35
  29. data/lib/volt/models/model_hash_behaviour.rb +15 -15
  30. data/lib/volt/models/model_helpers.rb +8 -8
  31. data/lib/volt/models/model_wrapper.rb +6 -6
  32. data/lib/volt/models/persistors/array_store.rb +36 -36
  33. data/lib/volt/models/persistors/base.rb +6 -6
  34. data/lib/volt/models/persistors/flash.rb +5 -5
  35. data/lib/volt/models/persistors/model_identity_map.rb +2 -2
  36. data/lib/volt/models/persistors/model_store.rb +22 -22
  37. data/lib/volt/models/persistors/params.rb +3 -3
  38. data/lib/volt/models/persistors/query/query_listener.rb +14 -14
  39. data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
  40. data/lib/volt/models/persistors/store.rb +8 -8
  41. data/lib/volt/models/persistors/store_factory.rb +2 -2
  42. data/lib/volt/models/url.rb +37 -37
  43. data/lib/volt/page/bindings/attribute_binding.rb +14 -14
  44. data/lib/volt/page/bindings/base_binding.rb +9 -9
  45. data/lib/volt/page/bindings/component_binding.rb +7 -7
  46. data/lib/volt/page/bindings/content_binding.rb +3 -3
  47. data/lib/volt/page/bindings/each_binding.rb +13 -13
  48. data/lib/volt/page/bindings/event_binding.rb +4 -4
  49. data/lib/volt/page/bindings/if_binding.rb +12 -12
  50. data/lib/volt/page/bindings/template_binding.rb +30 -30
  51. data/lib/volt/page/channel.rb +19 -19
  52. data/lib/volt/page/channel_stub.rb +6 -6
  53. data/lib/volt/page/document.rb +2 -2
  54. data/lib/volt/page/document_events.rb +4 -4
  55. data/lib/volt/page/draw_cycle.rb +3 -3
  56. data/lib/volt/page/memory_test.rb +6 -6
  57. data/lib/volt/page/page.rb +19 -19
  58. data/lib/volt/page/reactive_template.rb +9 -9
  59. data/lib/volt/page/sub_context.rb +5 -5
  60. data/lib/volt/page/targets/attribute_section.rb +9 -9
  61. data/lib/volt/page/targets/attribute_target.rb +3 -3
  62. data/lib/volt/page/targets/base_section.rb +2 -2
  63. data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
  64. data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
  65. data/lib/volt/page/targets/dom_section.rb +40 -38
  66. data/lib/volt/page/targets/dom_target.rb +2 -2
  67. data/lib/volt/page/tasks.rb +12 -12
  68. data/lib/volt/page/template_renderer.rb +4 -4
  69. data/lib/volt/page/url_tracker.rb +6 -6
  70. data/lib/volt/reactive/array_extensions.rb +2 -2
  71. data/lib/volt/reactive/destructive_methods.rb +5 -5
  72. data/lib/volt/reactive/event_chain.rb +25 -25
  73. data/lib/volt/reactive/events.rb +33 -33
  74. data/lib/volt/reactive/object_tracker.rb +21 -21
  75. data/lib/volt/reactive/object_tracking.rb +2 -2
  76. data/lib/volt/reactive/reactive_array.rb +57 -57
  77. data/lib/volt/reactive/reactive_tags.rb +16 -16
  78. data/lib/volt/reactive/reactive_value.rb +72 -72
  79. data/lib/volt/reactive/string_extensions.rb +3 -3
  80. data/lib/volt/router/routes.rb +22 -23
  81. data/lib/volt/server/component_handler.rb +5 -5
  82. data/lib/volt/server/component_templates.rb +14 -11
  83. data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
  84. data/lib/volt/server/html_parser/each_scope.rb +18 -0
  85. data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
  86. data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
  87. data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
  88. data/lib/volt/server/html_parser/view_handler.rb +82 -0
  89. data/lib/volt/server/html_parser/view_parser.rb +23 -0
  90. data/lib/volt/server/html_parser/view_scope.rb +145 -0
  91. data/lib/volt/server/rack/asset_files.rb +17 -17
  92. data/lib/volt/server/rack/component_paths.rb +18 -18
  93. data/lib/volt/server/rack/index_files.rb +8 -8
  94. data/lib/volt/server/rack/opal_files.rb +11 -11
  95. data/lib/volt/server/socket_connection_handler.rb +13 -13
  96. data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
  97. data/lib/volt/server.rb +18 -18
  98. data/lib/volt/tasks/dispatcher.rb +5 -5
  99. data/lib/volt/utils/ejson.rb +2 -2
  100. data/lib/volt/utils/generic_counting_pool.rb +8 -8
  101. data/lib/volt/utils/generic_pool.rb +16 -16
  102. data/lib/volt/volt/environment.rb +4 -4
  103. data/lib/volt.rb +6 -6
  104. data/spec/integration/test_integration_spec.rb +2 -2
  105. data/spec/models/event_chain_spec.rb +38 -38
  106. data/spec/models/model_spec.rb +128 -128
  107. data/spec/models/old_model_spec.rb +17 -17
  108. data/spec/models/persistors/params_spec.rb +3 -3
  109. data/spec/models/persistors/store_spec.rb +7 -7
  110. data/spec/models/reactive_array_spec.rb +82 -82
  111. data/spec/models/reactive_generator_spec.rb +11 -11
  112. data/spec/models/reactive_tags_spec.rb +6 -6
  113. data/spec/models/reactive_value_spec.rb +70 -70
  114. data/spec/models/store_spec.rb +4 -4
  115. data/spec/models/string_extensions_spec.rb +13 -13
  116. data/spec/page/bindings/content_binding_spec.rb +6 -6
  117. data/spec/page/sub_context_spec.rb +1 -1
  118. data/spec/router/routes_spec.rb +3 -3
  119. data/spec/server/html_parser/sample_page.html +595 -0
  120. data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
  121. data/spec/server/html_parser/view_parser_spec.rb +286 -0
  122. data/spec/server/rack/asset_files_spec.rb +6 -6
  123. data/spec/server/rack/component_paths_spec.rb +5 -5
  124. data/spec/spec_helper.rb +4 -5
  125. data/spec/store/mongo_spec.rb +3 -3
  126. data/spec/tasks/live_query_spec.rb +6 -6
  127. data/spec/tasks/query_tasks.rb +4 -4
  128. data/spec/tasks/query_tracker_spec.rb +20 -20
  129. data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
  130. data/spec/templates/template_binding_spec.rb +28 -28
  131. data/spec/utils/generic_counting_pool_spec.rb +5 -5
  132. data/spec/utils/generic_pool_spec.rb +14 -14
  133. data/templates/newgem/app/newgem/views/index/index.html +1 -2
  134. data/templates/project/app/home/config/dependencies.rb +1 -1
  135. data/templates/project/app/home/controllers/index_controller.rb +1 -1
  136. data/templates/project/app/home/views/index/about.html +4 -6
  137. data/templates/project/app/home/views/index/home.html +4 -5
  138. data/templates/project/app/home/views/index/index.html +8 -9
  139. data/templates/project/spec/spec_helper.rb +1 -1
  140. metadata +17 -8
  141. data/lib/volt/server/binding_setup.rb +0 -2
  142. data/lib/volt/server/if_binding_setup.rb +0 -31
  143. data/lib/volt/server/scope.rb +0 -43
  144. data/lib/volt/server/template_parser.rb +0 -453
  145. 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
@@ -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