volt 0.9.3.pre1 → 0.9.3.pre2

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +15 -1
  4. data/Gemfile +30 -3
  5. data/README.md +7 -2
  6. data/Rakefile +17 -0
  7. data/app/volt/models/user.rb +1 -1
  8. data/app/volt/tasks/live_query/live_query.rb +0 -1
  9. data/app/volt/tasks/live_query/live_query_pool.rb +8 -2
  10. data/app/volt/tasks/live_query/query_tracker.rb +2 -2
  11. data/app/volt/tasks/query_tasks.rb +10 -27
  12. data/app/volt/tasks/store_tasks.rb +6 -5
  13. data/app/volt/tasks/user_tasks.rb +2 -2
  14. data/docs/UPGRADE_GUIDE.md +14 -0
  15. data/lib/volt/boot.rb +1 -0
  16. data/lib/volt/cli/asset_compile.rb +25 -7
  17. data/lib/volt/cli/console.rb +6 -5
  18. data/lib/volt/cli/generate.rb +2 -2
  19. data/lib/volt/config.rb +2 -1
  20. data/lib/volt/controllers/http_controller.rb +4 -3
  21. data/lib/volt/controllers/model_controller.rb +41 -19
  22. data/lib/volt/controllers/template_helpers.rb +19 -0
  23. data/lib/volt/extra_core/array.rb +6 -0
  24. data/lib/volt/extra_core/hash.rb +8 -26
  25. data/lib/volt/extra_core/string.rb +1 -1
  26. data/lib/volt/models/array_model.rb +12 -4
  27. data/lib/volt/models/associations.rb +11 -13
  28. data/lib/volt/models/buffer.rb +1 -1
  29. data/lib/volt/models/model.rb +22 -13
  30. data/lib/volt/models/model_helpers/model_change_helpers.rb +0 -1
  31. data/lib/volt/models/model_helpers/model_helpers.rb +11 -0
  32. data/lib/volt/models/permissions.rb +9 -12
  33. data/lib/volt/models/persistors/array_store.rb +7 -7
  34. data/lib/volt/models/persistors/base.rb +9 -0
  35. data/lib/volt/models/persistors/cookies.rb +0 -4
  36. data/lib/volt/models/persistors/flash.rb +0 -4
  37. data/lib/volt/models/persistors/local_store.rb +0 -4
  38. data/lib/volt/models/persistors/model_store.rb +13 -21
  39. data/lib/volt/models/persistors/page.rb +22 -0
  40. data/lib/volt/models/persistors/params.rb +0 -4
  41. data/lib/volt/models/persistors/query/query_listener.rb +3 -2
  42. data/lib/volt/models/url.rb +2 -2
  43. data/lib/volt/models/validators/unique_validator.rb +1 -1
  44. data/lib/volt/models.rb +1 -0
  45. data/lib/volt/page/bindings/attribute_binding.rb +2 -2
  46. data/lib/volt/page/bindings/base_binding.rb +7 -3
  47. data/lib/volt/page/bindings/bindings.rb +9 -0
  48. data/lib/volt/page/bindings/content_binding.rb +2 -2
  49. data/lib/volt/page/bindings/each_binding.rb +16 -12
  50. data/lib/volt/page/bindings/event_binding.rb +4 -4
  51. data/lib/volt/page/bindings/if_binding.rb +3 -3
  52. data/lib/volt/page/bindings/view_binding.rb +4 -4
  53. data/lib/volt/page/bindings/yield_binding.rb +3 -3
  54. data/lib/volt/page/channel.rb +6 -0
  55. data/lib/volt/page/channel_stub.rb +1 -1
  56. data/lib/volt/page/page.rb +20 -54
  57. data/lib/volt/page/path_string_renderer.rb +5 -6
  58. data/lib/volt/page/string_template_renderer.rb +2 -2
  59. data/lib/volt/page/targets/attribute_section.rb +47 -0
  60. data/lib/volt/page/targets/base_section.rb +5 -5
  61. data/lib/volt/page/targets/binding_document/component_node.rb +6 -1
  62. data/lib/volt/page/template_renderer.rb +4 -4
  63. data/lib/volt/reactive/computation.rb +32 -3
  64. data/lib/volt/router/routes.rb +5 -5
  65. data/lib/volt/server/component_templates.rb +30 -2
  66. data/lib/volt/server/forking_server.rb +2 -2
  67. data/lib/volt/server/message_bus/base_message_bus.rb +52 -0
  68. data/lib/volt/server/message_bus/message_encoder.rb +64 -0
  69. data/lib/volt/server/message_bus/peer_to_peer/peer_connection.rb +186 -0
  70. data/lib/volt/server/message_bus/peer_to_peer/peer_server.rb +78 -0
  71. data/lib/volt/server/message_bus/peer_to_peer/server_tracker.rb +57 -0
  72. data/lib/volt/server/message_bus/peer_to_peer/socket_with_timeout.rb +27 -0
  73. data/lib/volt/server/message_bus/peer_to_peer.rb +198 -0
  74. data/lib/volt/server/message_bus/redis.rb +1 -0
  75. data/lib/volt/server/rack/asset_files.rb +2 -2
  76. data/lib/volt/server/rack/component_paths.rb +1 -1
  77. data/lib/volt/server/rack/http_resource.rb +3 -2
  78. data/lib/volt/server/rack/opal_files.rb +6 -9
  79. data/lib/volt/server/websocket/websocket_handler.rb +0 -3
  80. data/lib/volt/server.rb +5 -3
  81. data/lib/volt/spec/setup.rb +11 -12
  82. data/lib/volt/tasks/dispatcher.rb +8 -12
  83. data/lib/volt/tasks/task_handler.rb +3 -2
  84. data/lib/volt/utils/csso_patch.rb +24 -0
  85. data/lib/volt/utils/promise_patch.rb +2 -0
  86. data/lib/volt/version.rb +1 -1
  87. data/lib/volt/volt/app.rb +73 -36
  88. data/lib/volt/volt/server_setup/app.rb +81 -0
  89. data/lib/volt.rb +22 -1
  90. data/spec/apps/kitchen_sink/Gemfile +1 -1
  91. data/spec/controllers/http_controller_spec.rb +5 -3
  92. data/spec/controllers/model_controller_spec.rb +2 -2
  93. data/spec/extra_core/hash_spec.rb +9 -0
  94. data/spec/integration/list_spec.rb +3 -3
  95. data/spec/models/associations_spec.rb +10 -2
  96. data/spec/models/dirty_spec.rb +7 -7
  97. data/spec/models/model_spec.rb +10 -2
  98. data/spec/models/permissions_spec.rb +9 -0
  99. data/spec/models/persistors/store_spec.rb +8 -0
  100. data/spec/page/bindings/content_binding_spec.rb +6 -2
  101. data/spec/page/bindings/each_binding_spec.rb +59 -0
  102. data/spec/page/bindings/if_binding_spec.rb +57 -0
  103. data/spec/page/path_string_renderer_spec.rb +5 -5
  104. data/spec/reactive/computation_spec.rb +65 -1
  105. data/spec/router/routes_spec.rb +1 -1
  106. data/spec/server/html_parser/sandlebars_parser_spec.rb +12 -22
  107. data/spec/server/message_bus/message_encoder_spec.rb +49 -0
  108. data/spec/server/message_bus/peer_to_peer/peer_connection_spec.rb +108 -0
  109. data/spec/server/message_bus/peer_to_peer/peer_server_spec.rb +66 -0
  110. data/spec/server/message_bus/peer_to_peer/socket_with_timeout_spec.rb +11 -0
  111. data/spec/server/message_bus/peer_to_peer_spec.rb +11 -0
  112. data/spec/server/rack/asset_files_spec.rb +1 -1
  113. data/spec/server/rack/http_resource_spec.rb +4 -4
  114. data/spec/spec_helper.rb +16 -3
  115. data/spec/tasks/dispatcher_spec.rb +17 -5
  116. data/spec/tasks/live_query_spec.rb +1 -1
  117. data/spec/tasks/query_tracker_spec.rb +34 -34
  118. data/spec/tasks/user_tasks_spec.rb +4 -2
  119. data/templates/project/Gemfile.tt +14 -3
  120. data/templates/project/config/app.rb.tt +27 -2
  121. data/volt.gemspec +3 -8
  122. metadata +32 -101
  123. data/docs/FAQ.md +0 -7
@@ -0,0 +1,19 @@
1
+ module Volt
2
+ module TemplateHelpders
3
+ module ClassMethods
4
+ def template(name, template, bindings)
5
+ @templates[name] = { 'html' => template, 'bindings' => bindings }
6
+ end
7
+ end
8
+
9
+ def self.included(base)
10
+ # Setup blank templates class variable
11
+ base.class_attribute :__templates
12
+ base.__templates = {}
13
+
14
+ base.send :extend, ClassMethods
15
+ end
16
+ end
17
+
18
+
19
+ end
@@ -2,4 +2,10 @@ class Array
2
2
  def sum
3
3
  inject(0, :+)
4
4
  end
5
+
6
+ # For some reason .to_h doesn't show as defined in opal, but defined?(:to_h)
7
+ # returns true.
8
+ def to_h
9
+ Hash[self]
10
+ end
5
11
  end
@@ -1,26 +1,8 @@
1
- # module Hash
2
- # class Indifferent < Hash
3
- # def []=(key, value)
4
- # super(convert_key(key), value)
5
- # end
6
- #
7
- # def [](key)
8
- # super(convert_key(key))
9
- # end
10
- #
11
- # def key?(key)
12
- # super(convert_key(key))
13
- # end
14
- #
15
- # def fetch(key, *args)
16
- # super(convert_key(key), *args)
17
- # end
18
- #
19
- # private
20
- #
21
- # # Converts all keys to symbols for assignments
22
- # def convert_key(key)
23
- # key.is_a?(String) ? key : key.to_sym
24
- # end
25
- # end
26
- # end
1
+ class Hash
2
+ # Returns a hash excluding the keys passed in.
3
+ def without(*keys)
4
+ reject do |key, value|
5
+ keys.include?(key)
6
+ end
7
+ end
8
+ end
@@ -7,7 +7,7 @@ class String
7
7
  # Turns a string into the camel case version. If it is already camel case, it should
8
8
  # return the same string.
9
9
  def camelize(first_letter = :upper)
10
- new_str = gsub(/_[a-z]/) { |a| a[1].upcase }
10
+ new_str = gsub(/[_\-][a-z]/) { |a| a[1].upcase }
11
11
  new_str = new_str[0].capitalize + new_str[1..-1] if first_letter == :upper
12
12
 
13
13
  new_str
@@ -67,7 +67,7 @@ module Volt
67
67
  # Make sure it gets wrapped
68
68
  def <<(model)
69
69
  if model.is_a?(Model)
70
- # Set the new path
70
+ # Set the new path and the persistor.
71
71
  model.options = @options.merge(path: @options[:path] + [:[]])
72
72
  else
73
73
  model = wrap_values([model]).first
@@ -77,12 +77,17 @@ module Volt
77
77
  fail "permissions did not allow create for #{model.inspect}"
78
78
  end
79
79
 
80
+ # Add it to the array and trigger any watches or on events.
80
81
  super(model)
81
82
 
82
83
  if @persistor
83
84
  promise = @persistor.added(model, @array.size - 1)
84
85
  if promise && promise.is_a?(Promise)
85
86
  return promise.then do
87
+
88
+ # Mark the model as not new
89
+ model.instance_variable_set('@new', false)
90
+
86
91
  # Mark the model as loaded
87
92
  model.change_state_to(:loaded_state, :loaded)
88
93
 
@@ -191,8 +196,9 @@ module Volt
191
196
  Computation.run_without_tracking do
192
197
  # Track on size
193
198
  @size_dep.depend
194
- str = "#<#{self.class}:#{object_id} #{loaded_state}"
195
- str += " path:#{path.join('.')}" if path
199
+ str = "#<#{self.class}"
200
+ # str += " state:#{loaded_state}"
201
+ # str += " path:#{path.join('.')}" if path
196
202
  # str += " persistor:#{persistor.inspect}" if persistor
197
203
  str += " #{@array.inspect}>"
198
204
 
@@ -214,7 +220,9 @@ module Volt
214
220
 
215
221
  # Takes the persistor if there is one and
216
222
  def setup_persistor(persistor)
217
- @persistor = persistor.new(self) if persistor
223
+ # Use page as the default persistor
224
+ persistor ||= Persistors::Page
225
+ @persistor = persistor.new(self)
218
226
  end
219
227
  end
220
228
  end
@@ -2,28 +2,25 @@ module Volt
2
2
  module Associations
3
3
  module ClassMethods
4
4
  def belongs_to(method_name, key_name = nil)
5
+ key_name ||= "#{method_name}_id"
6
+ # Add a field for the association_id
7
+ field(key_name)
8
+
5
9
  # getter
6
10
  define_method(method_name) do
7
11
  association_with_root_model('belongs_to') do |root|
8
12
  # Lookup the associated model id
9
- lookup_key = send(:"_#{key_name || method_name}_id")
13
+ lookup_key = get(key_name)
10
14
 
11
15
  # Return a promise for the belongs_to
12
- root.send(:"_#{method_name.pluralize}").where(_id: lookup_key).fetch_first
16
+ root.get(method_name.pluralize).where(id: lookup_key).fetch_first
13
17
  end
14
18
  end
15
19
  end
16
20
 
17
21
  def has_many(method_name, remote_key_name = nil)
18
22
  define_method(method_name) do
19
- association_with_root_model('has_many') do |root|
20
- id = _id
21
-
22
- # The key will be "{this class name}_id"
23
- remote_key_name ||= :"#{path[-2].singularize}_id"
24
-
25
- root.send(:"_#{method_name.pluralize}!").where(remote_key_name => id)
26
- end
23
+ get(method_name.pluralize, true)
27
24
  end
28
25
  end
29
26
  end
@@ -37,10 +34,11 @@ module Volt
37
34
  # Currently the has_many and belongs_to associations only work on the store collection,
38
35
  # this method checks to make sure we are on store and returns the root reference to it.
39
36
  def association_with_root_model(method_name)
40
- persistor = self.persistor || (respond_to?(:save_to) && save_to.persistor)
37
+ persistor = self.persistor || (respond_to?(:save_to) && save_to && save_to.persistor)
41
38
 
42
39
  # Check if we are on the store collection
43
- if persistor.is_a?(Volt::Persistors::ModelStore)
40
+ if persistor.is_a?(Volt::Persistors::ModelStore) ||
41
+ persistor.is_a?(Volt::Persistors::Page)
44
42
  # Get the root node
45
43
  root = persistor.try(:root_model)
46
44
 
@@ -48,7 +46,7 @@ module Volt
48
46
  yield(root)
49
47
  else
50
48
  # raise an error about the method not being supported on this collection
51
- fail "#{method_name} currently only works on the store collection (support for other collections coming soon)"
49
+ fail "#{method_name} currently only works on the store and page collection (support for other collections coming soon)"
52
50
  end
53
51
  end
54
52
  end
@@ -33,7 +33,7 @@ module Volt
33
33
  new_model.change_state_to(:loaded_state, :loaded)
34
34
 
35
35
  # Set the buffer's id to track the main model's id
36
- attributes[:_id] = new_model._id
36
+ attributes[:id] = new_model.id
37
37
  options[:save_to] = new_model
38
38
  end
39
39
 
@@ -104,13 +104,16 @@ module Volt
104
104
  super
105
105
  end
106
106
 
107
- # the id is stored in a field named _id, so we setup _id to proxy to this
108
- def _id
109
- __id
107
+ def id
108
+ get(:id)
109
+ end
110
+
111
+ def id=(val)
112
+ set(:id, val)
110
113
  end
111
114
 
112
- def _id=(val)
113
- self.__id = val
115
+ def _id
116
+ raise "Accessing _id has been deprecated in favor of id"
114
117
  end
115
118
 
116
119
  # Return true if the model hasn't been saved yet
@@ -302,14 +305,14 @@ module Volt
302
305
 
303
306
  def inspect
304
307
  Computation.run_without_tracking do
305
- str = "<#{self.class}:#{object_id}"
308
+ str = "<#{self.class}"
306
309
 
307
310
  # Get path, loaded_state, and persistor, but cache in local var
308
- path = self.path
309
- str += " path:#{path}" if path
311
+ # path = self.path
312
+ # str += " path:#{path}" if path
310
313
 
311
- loaded_state = self.loaded_state
312
- str += " state:#{loaded_state}" if loaded_state
314
+ # loaded_state = self.loaded_state
315
+ # str += " state:#{loaded_state}" if loaded_state
313
316
 
314
317
  persistor = self.persistor
315
318
  # str += " persistor:#{persistor.inspect}" if persistor
@@ -339,7 +342,6 @@ module Volt
339
342
 
340
343
  private
341
344
  def run_initial_setup(initial_setup)
342
-
343
345
  # Save the changes
344
346
  if initial_setup
345
347
  # Run initial validation
@@ -372,7 +374,9 @@ module Volt
372
374
 
373
375
  # Takes the persistor if there is one and
374
376
  def setup_persistor(persistor)
375
- @persistor = persistor.new(self) if persistor
377
+ # Use page as the default persistor
378
+ persistor ||= Persistors::Page
379
+ @persistor = persistor.new(self)
376
380
  end
377
381
 
378
382
  # Used internally from other methods that assign all attributes
@@ -390,9 +394,14 @@ module Volt
390
394
  send(:"#{key}=", value)
391
395
  else
392
396
  # Otherwise, use the _ version
393
- send(:"_#{key}=", value)
397
+ set(key, value)
394
398
  end
395
399
  end
400
+
401
+ # Make an id if there isn't one yet
402
+ if @attributes[:id].nil? && persistor.try(:auto_generate_id)
403
+ self.id = generate_id
404
+ end
396
405
  end
397
406
  end
398
407
  end
@@ -46,7 +46,6 @@ module Volt
46
46
  nil
47
47
  end
48
48
 
49
-
50
49
  # Should only be called from run_changed. Saves the changes back to the persistor
51
50
  # and clears the tracked changes.
52
51
  def persist_changes(attribute_name)
@@ -21,6 +21,17 @@ module Volt
21
21
  @persistor.event_removed(event, last, last_for_event) if @persistor
22
22
  end
23
23
 
24
+ ID_CHARS = [('a'..'f'), ('0'..'9')].map(&:to_a).flatten
25
+
26
+ # Create a random unique id that can be used as the mongo id as well
27
+ def generate_id
28
+ id = []
29
+ 24.times { id << ID_CHARS.sample }
30
+
31
+ id.join
32
+ end
33
+
34
+
24
35
  module ClassMethods
25
36
  # Gets the class for a model at the specified path.
26
37
  def class_at_path(path)
@@ -9,7 +9,13 @@ module Volt
9
9
  #
10
10
  # @param key [Symbol] the name of the attribute to store
11
11
  def own_by_user(key = :user_id)
12
- # When the model is created, assign it the user_id (if the user is logged in)
12
+ relation, pattern = key.to_s, /_id$/
13
+ if relation.match(pattern)
14
+ belongs_to key.to_s.gsub(pattern, '')
15
+ else
16
+ raise "You tried to auto associate a model using #{key}, but #{key} "\
17
+ "does not end in `_id`"
18
+ end # When the model is created, assign it the user_id (if the user is logged in)
13
19
  on(:new) do
14
20
  # Only assign the user_id if there isn't already one and the user is logged in.
15
21
  if _user_id.nil? && !(user_id = Volt.current_user_id).nil?
@@ -33,15 +39,6 @@ module Volt
33
39
  end
34
40
  end
35
41
 
36
- # TODO: Change to
37
- # permissions(:create, :read, :update) do |action|
38
- # if owner?
39
- # allow
40
- # else
41
- # deny :user_id
42
- # end
43
- # end
44
-
45
42
  # permissions takes a block and yields
46
43
  def permissions(*actions, &block)
47
44
  # Store the permissions block so we can run it in validations
@@ -156,14 +153,14 @@ module Volt
156
153
 
157
154
  if allow && allow != true && allow.size > 0
158
155
  # always keep id
159
- allow << :_id
156
+ allow << :id
160
157
 
161
158
  # Only keep fields in the allow list
162
159
  return @attributes.select { |key| allow.include?(key) }
163
160
  elsif deny == true
164
161
  # Only keep id
165
162
  # TODO: Should this be a full reject?
166
- return @attributes.reject { |key| key != :_id }
163
+ return @attributes.reject { |key| key != :id }
167
164
  elsif deny && deny.size > 0
168
165
  # Reject any in the deny list
169
166
  return @attributes.reject { |key| deny.include?(key) }
@@ -134,10 +134,10 @@ module Volt
134
134
 
135
135
  parent.persistor.ensure_setup if parent.persistor
136
136
 
137
- if parent && (attrs = parent.attributes) && attrs[:_id]
137
+ if parent && (attrs = parent.attributes) && attrs[:id]
138
138
  query = query.dup
139
139
 
140
- query << [:find, { :"#{@model.path[-3].singularize}_id" => attrs[:_id] }]
140
+ query << [:find, { :"#{@model.path[-3].singularize}_id" => attrs[:id] }]
141
141
  end
142
142
  end
143
143
 
@@ -208,7 +208,7 @@ module Volt
208
208
  $loading_models = true
209
209
 
210
210
  Model.no_validate do
211
- data_id = data['_id'] || data[:_id]
211
+ data_id = data['id'] || data[:id]
212
212
 
213
213
  # Don't add if the model is already in the ArrayModel (from the client already)
214
214
  unless @ids[data_id]
@@ -232,7 +232,7 @@ module Volt
232
232
  ids.each do |id|
233
233
  # TODO: optimize this delete so we don't need to loop
234
234
  @model.each_with_index do |model, index|
235
- if model._id == id
235
+ if model.id == id
236
236
  @ids.delete(id)
237
237
  del = @model.delete_at(index)
238
238
  break
@@ -259,7 +259,7 @@ module Volt
259
259
  promise = model.persistor.add_to_collection
260
260
 
261
261
  # Track the the model got added
262
- @ids[model._id] = true
262
+ @ids[model.id] = true
263
263
 
264
264
  promise
265
265
  end
@@ -271,13 +271,13 @@ module Volt
271
271
  # Tell the persistor it was removed
272
272
  model.persistor.remove_from_collection
273
273
 
274
- @ids.delete(model._id)
274
+ @ids.delete(model.id)
275
275
  end
276
276
 
277
277
  if defined?($loading_models) && $loading_models
278
278
  return
279
279
  else
280
- StoreTasks.delete(channel_name, model.attributes[:_id])
280
+ StoreTasks.delete(channel_name, model.attributes[:id])
281
281
  end
282
282
  end
283
283
  end
@@ -2,6 +2,10 @@ module Volt
2
2
  module Persistors
3
3
  # Implements the base persistor functionality.
4
4
  class Base
5
+ def initialize(model)
6
+ @model = model
7
+ end
8
+
5
9
  def loaded(initial_state = nil)
6
10
  @model.change_state_to(:loaded_state, initial_state || :loaded)
7
11
  end
@@ -27,6 +31,11 @@ module Volt
27
31
  def event_removed(event, last, last_for_event)
28
32
  end
29
33
 
34
+ # Specify if this collection should auto-generate id's
35
+ def auto_generate_id
36
+ false
37
+ end
38
+
30
39
  # Find the root for this model
31
40
  def root_model
32
41
  node = @model
@@ -45,10 +45,6 @@ module Volt
45
45
  `document.cookie = cookie_val`
46
46
  end
47
47
 
48
- def initialize(model)
49
- @model = model
50
- end
51
-
52
48
  # Called when a model is added to the collection
53
49
  def added(model, index)
54
50
  # Save an added cookie
@@ -3,10 +3,6 @@ require 'volt/models/persistors/base'
3
3
  module Volt
4
4
  module Persistors
5
5
  class Flash < Base
6
- def initialize(model)
7
- @model = model
8
- end
9
-
10
6
  def added(model, index)
11
7
  if Volt.client?
12
8
  # Setup a new timer for clearing the flash.
@@ -6,10 +6,6 @@ module Volt
6
6
  module Persistors
7
7
  # Backs a collection in the local store
8
8
  class LocalStore < Base
9
- def initialize(model)
10
- @model = model
11
- end
12
-
13
9
  # Called when a model is added to the collection
14
10
  def added(model, index)
15
11
  root_model.persistor.save_all
@@ -11,8 +11,6 @@ module Volt
11
11
  class ModelStore < Store
12
12
  include StoreState
13
13
 
14
- ID_CHARS = [('a'..'f'), ('0'..'9')].map(&:to_a).flatten
15
-
16
14
  attr_reader :model
17
15
  attr_accessor :in_identity_map
18
16
 
@@ -40,32 +38,23 @@ module Volt
40
38
  @in_collection = false
41
39
  end
42
40
 
41
+ def auto_generate_id
42
+ true
43
+ end
44
+
43
45
  # Called the first time a value is assigned into this model
44
46
  def ensure_setup
45
- if (attrs = @model.attributes)
46
- # Do a nil check incase there is a nil model there
47
- @model.__id = generate_id if attrs[:_id].nil?
48
-
49
- add_to_identity_map
50
- end
47
+ add_to_identity_map
51
48
  end
52
49
 
53
50
  def add_to_identity_map
54
51
  unless @in_identity_map
55
- @@identity_map.add(@model._id, @model)
52
+ @@identity_map.add(@model.id, @model)
56
53
 
57
54
  @in_identity_map = true
58
55
  end
59
56
  end
60
57
 
61
- # Create a random unique id that can be used as the mongo id as well
62
- def generate_id
63
- id = []
64
- 24.times { id << ID_CHARS.sample }
65
-
66
- id.join
67
- end
68
-
69
58
  def save_changes?
70
59
  if RUBY_PLATFORM == 'opal'
71
60
  !(defined?($loading_models) && $loading_models) && @tasks
@@ -85,7 +74,7 @@ module Volt
85
74
  path_size = path.size
86
75
  if save_changes? && path_size > 0 && !@model.nil?
87
76
  if path_size > 3 && (parent = @model.parent) && (source = parent.parent)
88
- @model.attributes[:"#{path[-4].singularize}_id"] = source._id
77
+ @model.attributes[:"#{path[-4].singularize}_id"] = source.id
89
78
  end
90
79
 
91
80
  if !collection
@@ -152,7 +141,7 @@ module Volt
152
141
 
153
142
  if model
154
143
  data.each_pair do |key, value|
155
- model.send(:"_#{key}=", value) if key != :_id
144
+ model.set(key, value)# if key != :id
156
145
  end
157
146
  end
158
147
  end
@@ -186,7 +175,7 @@ module Volt
186
175
  return errors if errors.present?
187
176
 
188
177
  # Passed, save it
189
- id = values[:_id]
178
+ id = values[:id]
190
179
 
191
180
  # Try to create
192
181
  update_result = db.update(collection, values)
@@ -194,7 +183,10 @@ module Volt
194
183
  # An error hash will be returned if the update doesn't work
195
184
  return update_result if update_result
196
185
 
197
- QueryTasks.live_query_pool.updated_collection(collection.to_s, Thread.current['in_channel'])
186
+ # If we are running in a task, or the console, push update
187
+ if (volt_app = Volt.current_app)
188
+ volt_app.live_query_pool.updated_collection(collection.to_s, Thread.current['in_channel'])
189
+ end
198
190
  {}
199
191
  end
200
192
  end
@@ -0,0 +1,22 @@
1
+ require 'volt/models/persistors/base'
2
+
3
+ module Volt
4
+ module Persistors
5
+ class Page < Base
6
+ def auto_generate_id
7
+ true
8
+ end
9
+
10
+ def where(query)
11
+ @model.select do |model|
12
+ # Filter through each part of the query and make sure it matches.
13
+ query.each_pair do |key, value|
14
+ next false unless model.get(key) == value
15
+ end
16
+
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -3,10 +3,6 @@ require 'volt/models/persistors/base'
3
3
  module Volt
4
4
  module Persistors
5
5
  class Params < Base
6
- def initialize(model)
7
- @model = model
8
- end
9
-
10
6
  def changed(attribute_name)
11
7
  if RUBY_PLATFORM == 'opal'
12
8
  `
@@ -40,8 +40,9 @@ module Volt
40
40
  end
41
41
  end.fail do |err|
42
42
  # TODO: need to make it so we can re-raise out of this promise
43
- Volt.logger.error("Error adding listener: #{err.inspect}")
44
- Volt.logger.error(err.backtrace) if err.respond_to?(:backtrace)
43
+ msg = "Error adding listener: #{err.inspect}"
44
+ msg += "\n#{err.backtrace.join("\n")}" if err.respond_to?(:backtrace)
45
+ Volt.logger.error(msg)
45
46
 
46
47
  # If we get back that the user signature is wrong, log the user out.
47
48
  if err.to_s.start_with?('user id or hash is incorrectly signed')
@@ -102,7 +102,7 @@ module Volt
102
102
  # browser should be updated
103
103
  # Called when an attribute changes to update the url
104
104
  def update!
105
- if Volt.client?
105
+ if Volt.in_browser?
106
106
  new_url = url_for(@params.to_h)
107
107
 
108
108
  # Push the new url if pushState is supported
@@ -116,7 +116,7 @@ module Volt
116
116
  end
117
117
 
118
118
  def scroll
119
- if Volt.client?
119
+ if Volt.in_browser?
120
120
  frag = fragment
121
121
  if frag.present?
122
122
  # Scroll to anchor via http://www.w3.org/html/wg/drafts/html/master/browsers.html#scroll-to-fragid
@@ -8,7 +8,7 @@ module Volt
8
8
  query = {}
9
9
  # Check to see if any other documents have this value.
10
10
  query[field_name.to_s] = value
11
- query['_id'] = { '$ne' => model._id }
11
+ query['id'] = { '$ne' => model.id }
12
12
 
13
13
  # Check if the value is taken
14
14
  # TODO: need a way to handle scope for unique
data/lib/volt/models.rb CHANGED
@@ -2,6 +2,7 @@ require 'volt/extra_core/extra_core'
2
2
  require 'volt/models/model'
3
3
  require 'volt/models/cursor'
4
4
  require 'volt/models/persistors/store_factory'
5
+ require 'volt/models/persistors/page'
5
6
  require 'volt/models/persistors/array_store'
6
7
  require 'volt/models/persistors/model_store'
7
8
  require 'volt/models/persistors/params'
@@ -3,8 +3,8 @@ require 'volt/page/targets/attribute_target'
3
3
 
4
4
  module Volt
5
5
  class AttributeBinding < BaseBinding
6
- def initialize(page, target, context, binding_name, attribute_name, getter, setter)
7
- super(page, target, context, binding_name)
6
+ def initialize(volt_app, target, context, binding_name, attribute_name, getter, setter)
7
+ super(volt_app, target, context, binding_name)
8
8
 
9
9
  @attribute_name = attribute_name
10
10
  @getter = getter
@@ -10,10 +10,10 @@
10
10
  # binding will be inserted.
11
11
  module Volt
12
12
  class BaseBinding
13
- attr_accessor :target, :context, :binding_name
13
+ attr_accessor :target, :context, :binding_name, :volt_app
14
14
 
15
- def initialize(page, target, context, binding_name)
16
- @page = page
15
+ def initialize(volt_app, target, context, binding_name)
16
+ @volt_app = volt_app
17
17
  @target = target
18
18
  @context = context
19
19
  @binding_name = binding_name
@@ -21,6 +21,10 @@ module Volt
21
21
  @@binding_number ||= 10_000
22
22
  end
23
23
 
24
+ def page
25
+ @volt_app.page
26
+ end
27
+
24
28
  def dom_section
25
29
  @dom_section ||= target.dom_section(@binding_name)
26
30
  end