hyper-model 1.0.alpha1.3 → 1.0.alpha1.8

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.rspec +0 -1
  4. data/Gemfile +6 -5
  5. data/Rakefile +18 -6
  6. data/hyper-model.gemspec +12 -20
  7. data/lib/active_record_base.rb +95 -28
  8. data/lib/enumerable/pluck.rb +3 -2
  9. data/lib/hyper-model.rb +4 -1
  10. data/lib/hyper_model/version.rb +1 -1
  11. data/lib/hyper_react/input_tags.rb +2 -1
  12. data/lib/reactive_record/active_record/associations.rb +125 -35
  13. data/lib/reactive_record/active_record/base.rb +32 -0
  14. data/lib/reactive_record/active_record/class_methods.rb +125 -53
  15. data/lib/reactive_record/active_record/error.rb +2 -0
  16. data/lib/reactive_record/active_record/errors.rb +8 -4
  17. data/lib/reactive_record/active_record/instance_methods.rb +73 -5
  18. data/lib/reactive_record/active_record/public_columns_hash.rb +25 -26
  19. data/lib/reactive_record/active_record/reactive_record/backing_record_inspector.rb +22 -5
  20. data/lib/reactive_record/active_record/reactive_record/base.rb +50 -24
  21. data/lib/reactive_record/active_record/reactive_record/collection.rb +196 -63
  22. data/lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb +22 -0
  23. data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +27 -15
  24. data/lib/reactive_record/active_record/reactive_record/getters.rb +33 -10
  25. data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +71 -44
  26. data/lib/reactive_record/active_record/reactive_record/lookup_tables.rb +5 -5
  27. data/lib/reactive_record/active_record/reactive_record/operations.rb +7 -1
  28. data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +3 -6
  29. data/lib/reactive_record/active_record/reactive_record/setters.rb +105 -68
  30. data/lib/reactive_record/active_record/reactive_record/while_loading.rb +22 -1
  31. data/lib/reactive_record/broadcast.rb +59 -25
  32. data/lib/reactive_record/interval.rb +3 -3
  33. data/lib/reactive_record/permissions.rb +1 -1
  34. data/lib/reactive_record/scope_description.rb +3 -2
  35. data/lib/reactive_record/server_data_cache.rb +78 -48
  36. data/polymorph-notes.md +143 -0
  37. metadata +52 -157
  38. data/Gemfile.lock +0 -440
@@ -168,12 +168,12 @@ end
168
168
  module Kernel
169
169
  # (see Browser::Window#after)
170
170
  def after(time, &block)
171
- `setTimeout(#{block.to_n}, time * 1000)`
171
+ $window.after(time, &block)
172
172
  end
173
173
 
174
174
  # (see Browser::Window#after!)
175
175
  def after!(time, &block)
176
- `setTimeout(#{block.to_n}, time * 1000)`
176
+ $window.after!(time, &block)
177
177
  end
178
178
  end
179
179
 
@@ -187,4 +187,4 @@ class Proc
187
187
  def after!(time)
188
188
  $window.after!(time, &self)
189
189
  end
190
- end
190
+ end
@@ -90,7 +90,7 @@ class ActiveRecord::Base
90
90
  def belongs_to(attr_name, *args)
91
91
  belongs_to_without_reactive_record_add_is_method(attr_name, *args).tap do
92
92
  define_method "#{attr_name}_is?".to_sym do |model|
93
- self.class.reflections[attr_name.to_s].foreign_key == model.id
93
+ attributes[self.class.reflections[attr_name.to_s].foreign_key] == model.id
94
94
  end
95
95
  end
96
96
  end
@@ -93,8 +93,9 @@ module ReactiveRecord
93
93
  vector = []
94
94
  path.split('.').inject(@model) do |model, attribute|
95
95
  association = model.reflect_on_association(attribute)
96
- raise build_error(path, model, attribute) unless association
97
- vector = [association.inverse_of, *vector]
96
+ inverse_of = association.inverse_of if association
97
+ raise build_error(path, model, attribute) unless inverse_of
98
+ vector = [inverse_of, *vector]
98
99
  @joins[association.klass] << vector
99
100
  association.klass
100
101
  end
@@ -260,45 +260,54 @@ module ReactiveRecord
260
260
  def apply_method_to_cache(method)
261
261
  @db_cache.cache.inject(nil) do |representative, cache_item|
262
262
  if cache_item.vector == vector
263
- if method == "*"
264
- # apply_star does the security check if value is present
265
- cache_item.apply_star || representative
266
- elsif method == "*all"
267
- # if we secure the collection then we assume its okay to read the ids
268
- secured_value = cache_item.value.__secure_collection_check(cache_item)
269
- cache_item.build_new_cache_item(timing(:active_record) { secured_value.collect { |record| record.id } }, method, method)
270
- elsif method == "*count"
271
- secured_value = cache_item.value.__secure_collection_check(cache_item)
272
- cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.__secure_collection_check(cache_item).count }, method, method)
273
- elsif preloaded_value = @preloaded_records[cache_item.absolute_vector + [method]]
274
- # no security check needed since we already evaluated this
275
- cache_item.build_new_cache_item(preloaded_value, method, method)
276
- elsif aggregation = cache_item.aggregation?(method)
277
- # aggregations are not protected
278
- cache_item.build_new_cache_item(aggregation.mapping.collect { |attribute, accessor| cache_item.value[attribute] }, method, method)
279
- else
280
- if !cache_item.value || cache_item.value.is_a?(Array)
281
- # seeing as we just returning representative, no check is needed (its already checked)
282
- representative
263
+ begin
264
+ # error_recovery_method holds the current method that we are attempting to apply
265
+ # in case we throw an exception, and need to give the developer a meaningful message.
266
+ if method == "*"
267
+ # apply_star does the security check if value is present
268
+ cache_item.apply_star || representative
269
+ elsif method == "*all"
270
+ # if we secure the collection then we assume its okay to read the ids
271
+ error_recovery_method = [:all]
272
+ secured_value = cache_item.value.__secure_collection_check(cache_item)
273
+ cache_item.build_new_cache_item(timing(:active_record) { secured_value.collect { |record| record.id } }, method, method)
274
+ elsif method == "*count"
275
+ error_recovery_method = [:count]
276
+ secured_value = cache_item.value.__secure_collection_check(cache_item)
277
+ cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.__secure_collection_check(cache_item).count }, method, method)
278
+ elsif preloaded_value = @preloaded_records[cache_item.absolute_vector + [method]]
279
+ # no security check needed since we already evaluated this
280
+ cache_item.build_new_cache_item(preloaded_value, method, method)
281
+ elsif aggregation = cache_item.aggregation?(method)
282
+ # aggregations are not protected
283
+ error_recovery_method = [method, :mapping, :all]
284
+ cache_item.build_new_cache_item(aggregation.mapping.collect { |attribute, accessor| cache_item.value[attribute] }, method, method)
283
285
  else
284
- begin
285
- secured_method = "__secure_remote_access_to_#{[*method].first}"
286
-
287
- # order is important. This check must be first since scopes can have same name as attributes!
288
- if cache_item.value.respond_to? secured_method
289
- cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.send(secured_method, cache_item.value, @acting_user, *([*method][1..-1])) }, method, method)
290
- elsif (cache_item.value.class < ActiveRecord::Base) && cache_item.value.attributes.has_key?(method) # TODO: second check is not needed, its built into check_permmissions, check should be does class respond to check_permissions...
291
- cache_item.value.check_permission_with_acting_user(@acting_user, :view_permitted?, method)
292
- cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.send(*method) }, method, method)
293
- else
294
- raise "method missing"
286
+ if !cache_item.value || cache_item.value.is_a?(Array)
287
+ # seeing as we just returning representative, no check is needed (its already checked)
288
+ representative
289
+ elsif method == 'model_name'
290
+ error_recovery_method = [:model_name]
291
+ cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.model_name }, method, method)
292
+ else
293
+ begin
294
+ secured_method = "__secure_remote_access_to_#{[*method].first}"
295
+ error_recovery_method = [*method]
296
+ # order is important. This check must be first since scopes can have same name as attributes!
297
+ if cache_item.value.respond_to? secured_method
298
+ cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.send(secured_method, cache_item.value, @acting_user, *([*method][1..-1])) }, method, method)
299
+ elsif (cache_item.value.class < ActiveRecord::Base) && cache_item.value.attributes.has_key?(method) # TODO: second check is not needed, its built into check_permmissions, check should be does class respond to check_permissions...
300
+ cache_item.value.check_permission_with_acting_user(@acting_user, :view_permitted?, method)
301
+ cache_item.build_new_cache_item(timing(:active_record) { cache_item.value.send(*method) }, method, method)
302
+ else
303
+ raise "Method missing while fetching data: \`#{[*method].first}\` "\
304
+ 'was expected to be an attribute or a method defined using the server_method of finder_method macros.'
305
+ end
295
306
  end
296
- # rescue Exception => e # this check may no longer be needed as we are quite explicit now on which methods we apply
297
- # # ReactiveRecord::Pry::rescued(e)
298
- # #::Rails.logger.debug "\033[0;31;1mERROR: HyperModel exception caught when applying #{method} to db object #{cache_item.value}: #{e}\033[0;30;21m"
299
- # raise e, "HyperModel fetching records failed, exception caught when applying #{method} to db object #{cache_item.value}: #{e}", e.backtrace
300
307
  end
301
308
  end
309
+ rescue StandardError => e
310
+ raise e.class, form_error_message(e, cache_item.vector + error_recovery_method), e.backtrace
302
311
  end
303
312
  else
304
313
  representative
@@ -306,6 +315,15 @@ module ReactiveRecord
306
315
  end
307
316
  end
308
317
 
318
+ def form_error_message(original_error, vector)
319
+ expression = vector.collect do |exp|
320
+ next exp unless exp.is_a? Array
321
+ next exp.first if exp.length == 1
322
+ "#{exp.first}(#{exp[1..-1].join(', ')})"
323
+ end.join('.')
324
+ "raised when evaluating #{expression}\n#{original_error}"
325
+ end
326
+
309
327
  def aggregation?(method)
310
328
  if method.is_a?(String) && @value.class.respond_to?(:reflect_on_aggregation)
311
329
  aggregation = @value.class.reflect_on_aggregation(method.to_sym)
@@ -378,6 +396,8 @@ module ReactiveRecord
378
396
  if method == "*"
379
397
  if @value.is_a? Array # this happens when a scope is empty there is test case, but
380
398
  @parent.as_hash({}) # does it work for all edge cases?
399
+ elsif (@value.class < ActiveRecord::Base) && children.is_a?(Hash)
400
+ @parent.as_hash({@value.id => merge_inheritance_column(children)})
381
401
  else
382
402
  @parent.as_hash({@value.id => children})
383
403
  end
@@ -431,17 +451,30 @@ keys:
431
451
  if value is a hash
432
452
  =end
433
453
 
434
-
435
454
  def self.load_from_json(tree, target = nil)
436
-
437
455
  # have to process *all before any other items
438
456
  # we leave the "*all" key in just for debugging purposes, and then skip it below
439
457
 
440
458
  if sorted_collection = tree["*all"]
441
- target.replace sorted_collection.collect { |id| target.proxy_association.klass.find(id) }
459
+ loaded_collection = sorted_collection.collect do |id|
460
+ ReactiveRecord::Base.find_by_id(target.proxy_association.klass, id)
461
+ end
462
+ if loaded_collection[0] && target.scope_description&.name == '___hyperstack_internal_scoped_find_by'
463
+ primary_key = target.proxy_association.klass.primary_key
464
+ attrs = target.vector[-1][1].reject { |key, _| key == primary_key }
465
+ loaded_collection[0].backing_record.sync_attributes(attrs)
466
+ end
467
+ target.replace loaded_collection
468
+ # we need to notify any observers of the collection. collection#replace
469
+ # will not notify if we are data_loading (which we are) so we will do it
470
+ # here. BUT we want the notification to occur after the current event
471
+ # completes so we wrap it a bulk_update
472
+ Hyperstack::Internal::State::Mapper.bulk_update do
473
+ Hyperstack::Internal::State::Variable.set(target, :collection, target.collection)
474
+ end
442
475
  end
443
476
 
444
- if id_value = tree["id"] and id_value.is_a? Array
477
+ if (id_value = tree[target.class.try(:primary_key)] || tree[:id]) && id_value.is_a?(Array)
445
478
  target.id = id_value.first
446
479
  end
447
480
  tree.each do |method, value|
@@ -453,17 +486,16 @@ keys:
453
486
  elsif !target
454
487
  load_from_json(value, Object.const_get(method))
455
488
  elsif method == "*count"
456
- target.set_count_state(value.first)
489
+ target.count_state = value.first
457
490
  elsif method.is_a? Integer or method =~ /^[0-9]+$/
458
491
  new_target = target.push_and_update_belongs_to(method)
459
- #target << (new_target = target.proxy_association.klass.find(method))
460
492
  elsif method.is_a? Array
461
493
  if method[0] == "new"
462
494
  new_target = ReactiveRecord::Base.lookup_by_object_id(method[1])
463
495
  elsif !(target.class < ActiveRecord::Base)
464
496
  new_target = target.send(*method)
465
497
  # value is an array if scope returns nil, so we destroy the bogus record
466
- new_target.destroy and new_target = nil if value.is_a? Array
498
+ new_target.destroy && (new_target = nil) if value.is_a? Array
467
499
  else
468
500
  target.backing_record.update_simple_attribute([method], target.backing_record.convert(method, value.first))
469
501
  end
@@ -474,12 +506,11 @@ keys:
474
506
 
475
507
  target.send "#{method}=", value.first
476
508
  elsif value.is_a? Array
477
- # we cannot use target.send "#{method}=" here because it might be a server method, which does not have a setter
478
- # a better fix might be something like target._internal_attribute_hash[method] = ...
479
- target.backing_record.set_attr_value(method, value.first) unless method == :id
480
- elsif value.is_a? Hash and value[:id] and value[:id].first and association = target.class.reflect_on_association(method)
509
+ target.send("_hyperstack_internal_setter_#{method}", value.first) unless [target.class.primary_key, :id].include? method
510
+ elsif value.is_a?(Hash) && value[:id] && value[:id].first && (association = target.class.reflect_on_association(method))
481
511
  # not sure if its necessary to check the id above... is it possible to for the method to be an association but not have an id?
482
- new_target = association.klass.find(value[:id].first)
512
+ klass = value[:model_name] ? Object.const_get(value[:model_name].first) : association.klass
513
+ new_target = ReactiveRecord::Base.find_by_id(klass, value[:id].first)
483
514
  target.send "#{method}=", new_target
484
515
  elsif !(target.class < ActiveRecord::Base)
485
516
  new_target = target.send(*method)
@@ -491,7 +522,6 @@ keys:
491
522
  load_from_json(value, new_target) if new_target
492
523
  end
493
524
  rescue Exception => e
494
- # debugger
495
525
  raise e
496
526
  end
497
527
  end
@@ -0,0 +1,143 @@
1
+ ```ruby
2
+ class Picture < ApplicationRecord
3
+ belongs_to :imageable, polymorphic: true
4
+ end
5
+
6
+ class Employee < ApplicationRecord
7
+ has_many :pictures, as: :imageable
8
+ end
9
+
10
+ class Product < ApplicationRecord
11
+ has_many :pictures, as: :imageable
12
+ end
13
+ ```
14
+
15
+ product|employee.pictures -> works almost as normal has_many as far as Hyperstack client is concerned
16
+ imageable is the "alias" of product|employee. Its as if there is a class Imageable that is the superclass
17
+ of Product and Employee.
18
+
19
+ so has_many :pictures means the usual thing (i.e. there is a belongs_to relationship on Picture) its just that
20
+ the belongs_to will be belonging to :imageable instead of :employee or :product.
21
+
22
+ okay fine
23
+
24
+ the other way:
25
+
26
+ the problem is that picture.imageable while loading is pointing to a dummy class (sure call it Imageable)
27
+ so if we say picture.imageable.foo.bar.blat what we get is a dummy value that responds to all methods, and returns itself:
28
+
29
+ picture.imageable -> imageable123 .foo -> imageable123 .bar -> ... etc. but it is a dummy value that will cause a fetch of the actual imageable record (or nil).
30
+
31
+ .imageable should be able to leverage off of server_method.
32
+
33
+ server_method(:imageable, PolymorphicDummy.new(:imageable))
34
+
35
+ hmmmm....
36
+
37
+ really its like doing a picture.imageable.itself (?) (that may work Juuuust fine)
38
+
39
+ so picture.imageable returns this funky dummy value but does an across the wire request for picture.imageable (which should get imageable_id per a normal relationship) and also get picture.imageable_type.
40
+
41
+
42
+ start again....
43
+
44
+ what happens if we ignore (on the client) the polymorphic: and as: keys?
45
+
46
+ belongs_to :imageable
47
+
48
+ means there is a class Imageable, okay so we make one, and add has_many :pictures to it.
49
+
50
+
51
+ and again....
52
+
53
+ ```ruby
54
+ def imageable
55
+ if imageable_type.loaded? && imageable_id.loaded?
56
+ const_get(imageable_type).find(imageable_id)
57
+ else
58
+ DummyImageable.new(self)
59
+ end
60
+ end
61
+ ```
62
+
63
+ very close but will not work for cases like this:
64
+
65
+ ```ruby
66
+ pic = Picture.new
67
+ employee.pictures << pic
68
+ pic.imageable # FAIL... (until its been saved)
69
+ ...
70
+ ```
71
+
72
+ but still it may be as simple as overriding `<<` so that it sets type on imageable. But we still to have a proper belongs to relationship.
73
+
74
+ ```ruby
75
+ def imageable
76
+ if we already have the attribute set
77
+ return the attribute
78
+ else
79
+ set attribute to DummyPolyClass.new(self, 'imageable')
80
+ # DummyPolyClass init will set up a fetch of the actual imageable value
81
+ end
82
+ end
83
+
84
+ def imageable=(x)
85
+ # will it just work ?
86
+ end
87
+ ```
88
+
89
+ its all about the collection inverse. The inverse class of the has_many is the class containing the polymorphic belongs to. But the inverse of a polymorphic belongs to depends on the value. If the value is nil or a DummyPolyClass object then there is no inverse.
90
+
91
+ I think if inverse takes this into account then `<<` and `=` should just "work" (well almost) and probably everything else will to.
92
+
93
+ ### NOTES on the DummyPolyClass...
94
+
95
+ it needs to respond to reflect_on_all_associations, but just return an empty array. This way when we search for matching inverse attribute we won't find it.
96
+
97
+ ### Status
98
+
99
+ added model to inverse, inverse_of, find_inverse
100
+
101
+ if the relationship is a collection then we will always know the inverse.
102
+
103
+ The only time we might no know the inverse is if its NOT a collection (i.e. belongs_to)
104
+
105
+ So only places that are applying inverse to an association that is NOT a collection do we have to pass the model in.
106
+
107
+ All inverse_of method calls have been checked and updated
108
+
109
+ that leaves inverse which is only used in SETTERS hurray!
110
+
111
+
112
+ ### Latest thinking
113
+
114
+ going from `has_many / has_one as: ...` is easy its essentially setting the association foreign_key using the name supplied to the as:
115
+
116
+ The problem is going from the polymorphic belongs_to side.
117
+
118
+ We don't know the actual type we are loading which presents two problems.
119
+
120
+ First we just don't know the type. So if I say `Picture.find(1).imageable.foo.bar` I really can't do anything with foo and bar. This is solved by having a DummyPolymorph class, which responds to all missing methods with itself, and on creation sets up a vector to pull it the id, and type of the record being fetched. This will cause a second fetch to actually get `foo.bar` because we don't know what they are yet. (Its cool beacuse this is like Type inference actually, and I think we could eventually use a type inference system to get rid of the second fetch!!!)
121
+
122
+ Second we don't know the inverse of the relationship (since we don't know the type)
123
+
124
+ We can solve this by aliasing the inverse relationship (the one with the `as: SOMENAME` option) to be `has_many #{__hyperstack_polymorphic_inverse_of_#{SOMENAME}` and then defining method(s) against the relationship name. This way regardless of what the polymorphic relationship points to we know the inverse is `__hyperstack_polymorphic_inverse_of_#{SOMENAME}`.
125
+
126
+ If the inverse relationship is a has_many then we define
127
+ ```ruby
128
+ def #{RELATIONSHIP_NAME}
129
+ __hyperstack_polymorphic_inverse_of_#{SOMENAME}
130
+ end
131
+ ```
132
+
133
+ If the inverse relationship is a has_one we have to work a bit harder:
134
+ ```ruby
135
+ def #{RELATIONSHIP_NAME}
136
+ __hyperstack_polymorphic_inverse_of_#{SOMENAME}[0]
137
+ end
138
+ def #{RELATIONSHIP_NAME}=(x)
139
+ __hyperstack_polymorphic_inverse_of_#{SOMENAME}[0] = x # or perhaps we have to replace the array using the internal method in collection for that purpose.
140
+ end
141
+ ```
142
+
143
+ The remaining problem is that the server side will have no such relationships defined so we need to add the `has_many __hyperstack_polymorphic_inverse_of_#{SOMENAME} as: SOMENAME` server side.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyper-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.alpha1.3
4
+ version: 1.0.alpha1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitch VanDuyn
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-01-17 00:00:00.000000000 Z
12
+ date: 2021-04-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -39,56 +39,36 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: 4.0.0
42
- - !ruby/object:Gem::Dependency
43
- name: hyper-component
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - '='
47
- - !ruby/object:Gem::Version
48
- version: 1.0.alpha1.3
49
- type: :runtime
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - '='
54
- - !ruby/object:Gem::Version
55
- version: 1.0.alpha1.3
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: hyper-operation
58
44
  requirement: !ruby/object:Gem::Requirement
59
45
  requirements:
60
46
  - - '='
61
47
  - !ruby/object:Gem::Version
62
- version: 1.0.alpha1.3
48
+ version: 1.0.alpha1.8
63
49
  type: :runtime
64
50
  prerelease: false
65
51
  version_requirements: !ruby/object:Gem::Requirement
66
52
  requirements:
67
53
  - - '='
68
54
  - !ruby/object:Gem::Version
69
- version: 1.0.alpha1.3
55
+ version: 1.0.alpha1.8
70
56
  - !ruby/object:Gem::Dependency
71
57
  name: bundler
72
58
  requirement: !ruby/object:Gem::Requirement
73
59
  requirements:
74
60
  - - ">="
75
61
  - !ruby/object:Gem::Version
76
- version: 1.17.3
77
- - - "<"
78
- - !ruby/object:Gem::Version
79
- version: '2.1'
62
+ version: '0'
80
63
  type: :development
81
64
  prerelease: false
82
65
  version_requirements: !ruby/object:Gem::Requirement
83
66
  requirements:
84
67
  - - ">="
85
68
  - !ruby/object:Gem::Version
86
- version: 1.17.3
87
- - - "<"
88
- - !ruby/object:Gem::Version
89
- version: '2.1'
69
+ version: '0'
90
70
  - !ruby/object:Gem::Dependency
91
- name: capybara
71
+ name: database_cleaner
92
72
  requirement: !ruby/object:Gem::Requirement
93
73
  requirements:
94
74
  - - ">="
@@ -102,21 +82,7 @@ dependencies:
102
82
  - !ruby/object:Gem::Version
103
83
  version: '0'
104
84
  - !ruby/object:Gem::Dependency
105
- name: chromedriver-helper
106
- requirement: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 1.2.0
111
- type: :development
112
- prerelease: false
113
- version_requirements: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - '='
116
- - !ruby/object:Gem::Version
117
- version: 1.2.0
118
- - !ruby/object:Gem::Dependency
119
- name: libv8
85
+ name: factory_bot_rails
120
86
  requirement: !ruby/object:Gem::Requirement
121
87
  requirements:
122
88
  - - ">="
@@ -130,49 +96,35 @@ dependencies:
130
96
  - !ruby/object:Gem::Version
131
97
  version: '0'
132
98
  - !ruby/object:Gem::Dependency
133
- name: mini_racer
99
+ name: hyper-spec
134
100
  requirement: !ruby/object:Gem::Requirement
135
101
  requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: 0.2.4
139
- type: :development
140
- prerelease: false
141
- version_requirements: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 0.2.4
146
- - !ruby/object:Gem::Dependency
147
- name: selenium-webdriver
148
- requirement: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
102
+ - - '='
151
103
  - !ruby/object:Gem::Version
152
- version: '0'
104
+ version: 1.0.alpha1.8
153
105
  type: :development
154
106
  prerelease: false
155
107
  version_requirements: !ruby/object:Gem::Requirement
156
108
  requirements:
157
- - - ">="
109
+ - - '='
158
110
  - !ruby/object:Gem::Version
159
- version: '0'
111
+ version: 1.0.alpha1.8
160
112
  - !ruby/object:Gem::Dependency
161
- name: database_cleaner
113
+ name: hyper-trace
162
114
  requirement: !ruby/object:Gem::Requirement
163
115
  requirements:
164
- - - ">="
116
+ - - '='
165
117
  - !ruby/object:Gem::Version
166
- version: '0'
118
+ version: 1.0.alpha1.8
167
119
  type: :development
168
120
  prerelease: false
169
121
  version_requirements: !ruby/object:Gem::Requirement
170
122
  requirements:
171
- - - ">="
123
+ - - '='
172
124
  - !ruby/object:Gem::Version
173
- version: '0'
125
+ version: 1.0.alpha1.8
174
126
  - !ruby/object:Gem::Dependency
175
- name: factory_bot_rails
127
+ name: mini_racer
176
128
  requirement: !ruby/object:Gem::Requirement
177
129
  requirements:
178
130
  - - ">="
@@ -186,7 +138,7 @@ dependencies:
186
138
  - !ruby/object:Gem::Version
187
139
  version: '0'
188
140
  - !ruby/object:Gem::Dependency
189
- name: mysql2
141
+ name: pg
190
142
  requirement: !ruby/object:Gem::Requirement
191
143
  requirements:
192
144
  - - ">="
@@ -199,64 +151,28 @@ dependencies:
199
151
  - - ">="
200
152
  - !ruby/object:Gem::Version
201
153
  version: '0'
202
- - !ruby/object:Gem::Dependency
203
- name: opal-activesupport
204
- requirement: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: 0.3.1
209
- type: :development
210
- prerelease: false
211
- version_requirements: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - "~>"
214
- - !ruby/object:Gem::Version
215
- version: 0.3.1
216
- - !ruby/object:Gem::Dependency
217
- name: opal-browser
218
- requirement: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - "~>"
221
- - !ruby/object:Gem::Version
222
- version: 0.2.0
223
- type: :development
224
- prerelease: false
225
- version_requirements: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - "~>"
228
- - !ruby/object:Gem::Version
229
- version: 0.2.0
230
154
  - !ruby/object:Gem::Dependency
231
155
  name: opal-rails
232
156
  requirement: !ruby/object:Gem::Requirement
233
157
  requirements:
234
- - - "~>"
235
- - !ruby/object:Gem::Version
236
- version: 0.9.4
237
- type: :development
238
- prerelease: false
239
- version_requirements: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - "~>"
158
+ - - ">="
242
159
  - !ruby/object:Gem::Version
243
160
  version: 0.9.4
244
- - !ruby/object:Gem::Dependency
245
- name: parser
246
- requirement: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - ">="
161
+ - - "<"
249
162
  - !ruby/object:Gem::Version
250
- version: '0'
163
+ version: '2.0'
251
164
  type: :development
252
165
  prerelease: false
253
166
  version_requirements: !ruby/object:Gem::Requirement
254
167
  requirements:
255
168
  - - ">="
256
169
  - !ruby/object:Gem::Version
257
- version: '0'
170
+ version: 0.9.4
171
+ - - "<"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.0'
258
174
  - !ruby/object:Gem::Dependency
259
- name: pry
175
+ name: pry-rescue
260
176
  requirement: !ruby/object:Gem::Requirement
261
177
  requirements:
262
178
  - - ">="
@@ -270,7 +186,7 @@ dependencies:
270
186
  - !ruby/object:Gem::Version
271
187
  version: '0'
272
188
  - !ruby/object:Gem::Dependency
273
- name: pry-rescue
189
+ name: pry-stack_explorer
274
190
  requirement: !ruby/object:Gem::Requirement
275
191
  requirements:
276
192
  - - ">="
@@ -331,14 +247,20 @@ dependencies:
331
247
  requirements:
332
248
  - - ">="
333
249
  - !ruby/object:Gem::Version
334
- version: 4.0.0
250
+ version: 5.0.0
251
+ - - "<"
252
+ - !ruby/object:Gem::Version
253
+ version: '7.0'
335
254
  type: :development
336
255
  prerelease: false
337
256
  version_requirements: !ruby/object:Gem::Requirement
338
257
  requirements:
339
258
  - - ">="
340
259
  - !ruby/object:Gem::Version
341
- version: 4.0.0
260
+ version: 5.0.0
261
+ - - "<"
262
+ - !ruby/object:Gem::Version
263
+ version: '7.0'
342
264
  - !ruby/object:Gem::Dependency
343
265
  name: rake
344
266
  requirement: !ruby/object:Gem::Requirement
@@ -373,20 +295,6 @@ dependencies:
373
295
  - - "<"
374
296
  - !ruby/object:Gem::Version
375
297
  version: 2.5.0
376
- - !ruby/object:Gem::Dependency
377
- name: reactrb-rails-generator
378
- requirement: !ruby/object:Gem::Requirement
379
- requirements:
380
- - - ">="
381
- - !ruby/object:Gem::Version
382
- version: '0'
383
- type: :development
384
- prerelease: false
385
- version_requirements: !ruby/object:Gem::Requirement
386
- requirements:
387
- - - ">="
388
- - !ruby/object:Gem::Version
389
- version: '0'
390
298
  - !ruby/object:Gem::Dependency
391
299
  name: rspec-collection_matchers
392
300
  requirement: !ruby/object:Gem::Requirement
@@ -489,16 +397,16 @@ dependencies:
489
397
  name: rubocop
490
398
  requirement: !ruby/object:Gem::Requirement
491
399
  requirements:
492
- - - "~>"
400
+ - - ">="
493
401
  - !ruby/object:Gem::Version
494
- version: 0.51.0
402
+ version: '0'
495
403
  type: :development
496
404
  prerelease: false
497
405
  version_requirements: !ruby/object:Gem::Requirement
498
406
  requirements:
499
- - - "~>"
407
+ - - ">="
500
408
  - !ruby/object:Gem::Version
501
- version: 0.51.0
409
+ version: '0'
502
410
  - !ruby/object:Gem::Dependency
503
411
  name: shoulda
504
412
  requirement: !ruby/object:Gem::Requirement
@@ -531,30 +439,30 @@ dependencies:
531
439
  name: spring-commands-rspec
532
440
  requirement: !ruby/object:Gem::Requirement
533
441
  requirements:
534
- - - ">="
442
+ - - "~>"
535
443
  - !ruby/object:Gem::Version
536
- version: '0'
444
+ version: 1.0.4
537
445
  type: :development
538
446
  prerelease: false
539
447
  version_requirements: !ruby/object:Gem::Requirement
540
448
  requirements:
541
- - - ">="
449
+ - - "~>"
542
450
  - !ruby/object:Gem::Version
543
- version: '0'
451
+ version: 1.0.4
544
452
  - !ruby/object:Gem::Dependency
545
453
  name: sqlite3
546
454
  requirement: !ruby/object:Gem::Requirement
547
455
  requirements:
548
- - - ">="
456
+ - - "~>"
549
457
  - !ruby/object:Gem::Version
550
- version: '0'
458
+ version: 1.4.2
551
459
  type: :development
552
460
  prerelease: false
553
461
  version_requirements: !ruby/object:Gem::Requirement
554
462
  requirements:
555
- - - ">="
463
+ - - "~>"
556
464
  - !ruby/object:Gem::Version
557
- version: '0'
465
+ version: 1.4.2
558
466
  - !ruby/object:Gem::Dependency
559
467
  name: timecop
560
468
  requirement: !ruby/object:Gem::Requirement
@@ -569,20 +477,6 @@ dependencies:
569
477
  - - "~>"
570
478
  - !ruby/object:Gem::Version
571
479
  version: 0.8.1
572
- - !ruby/object:Gem::Dependency
573
- name: unparser
574
- requirement: !ruby/object:Gem::Requirement
575
- requirements:
576
- - - ">="
577
- - !ruby/object:Gem::Version
578
- version: '0'
579
- type: :development
580
- prerelease: false
581
- version_requirements: !ruby/object:Gem::Requirement
582
- requirements:
583
- - - ">="
584
- - !ruby/object:Gem::Version
585
- version: '0'
586
480
  description: HyperModel gives your HyperComponents CRUD access to your ActiveRecord
587
481
  models on the client, using the the standard ActiveRecord API. HyperModel also implements
588
482
  push notifications (via a number of possible technologies) so changes to records
@@ -598,7 +492,6 @@ files:
598
492
  - ".rspec"
599
493
  - ".travis.yml"
600
494
  - Gemfile
601
- - Gemfile.lock
602
495
  - Rakefile
603
496
  - bin/console
604
497
  - bin/setup
@@ -629,6 +522,7 @@ files:
629
522
  - lib/reactive_record/active_record/reactive_record/base.rb
630
523
  - lib/reactive_record/active_record/reactive_record/collection.rb
631
524
  - lib/reactive_record/active_record/reactive_record/column_types.rb
525
+ - lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb
632
526
  - lib/reactive_record/active_record/reactive_record/dummy_value.rb
633
527
  - lib/reactive_record/active_record/reactive_record/getters.rb
634
528
  - lib/reactive_record/active_record/reactive_record/isomorphic_base.rb
@@ -648,6 +542,7 @@ files:
648
542
  - lib/reactive_record/scope_description.rb
649
543
  - lib/reactive_record/serializers.rb
650
544
  - lib/reactive_record/server_data_cache.rb
545
+ - polymorph-notes.md
651
546
  - spec_fails.txt
652
547
  homepage: http://ruby-hyperstack.org
653
548
  licenses:
@@ -668,7 +563,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
668
563
  - !ruby/object:Gem::Version
669
564
  version: 1.3.1
670
565
  requirements: []
671
- rubygems_version: 3.0.2
566
+ rubygems_version: 3.0.8
672
567
  signing_key:
673
568
  specification_version: 4
674
569
  summary: React based CRUD access and Synchronization of active record models across