volt 0.9.3.pre1 → 0.9.3.pre2

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