volt 0.6.5 → 0.7.0

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