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

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