hyper-model 1.0.alpha1.1 → 1.0.alpha1.6

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.rspec +0 -1
  4. data/Gemfile +6 -6
  5. data/Rakefile +27 -3
  6. data/hyper-model.gemspec +10 -19
  7. data/lib/active_record_base.rb +101 -33
  8. data/lib/hyper-model.rb +4 -2
  9. data/lib/hyper_model/version.rb +1 -1
  10. data/lib/hyper_react/input_tags.rb +2 -1
  11. data/lib/reactive_record/active_record/associations.rb +130 -34
  12. data/lib/reactive_record/active_record/base.rb +17 -0
  13. data/lib/reactive_record/active_record/class_methods.rb +124 -52
  14. data/lib/reactive_record/active_record/error.rb +2 -0
  15. data/lib/reactive_record/active_record/errors.rb +10 -6
  16. data/lib/reactive_record/active_record/instance_methods.rb +74 -6
  17. data/lib/reactive_record/active_record/reactive_record/backing_record_inspector.rb +22 -5
  18. data/lib/reactive_record/active_record/reactive_record/base.rb +56 -30
  19. data/lib/reactive_record/active_record/reactive_record/collection.rb +219 -70
  20. data/lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb +22 -0
  21. data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +27 -15
  22. data/lib/reactive_record/active_record/reactive_record/getters.rb +33 -10
  23. data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +73 -46
  24. data/lib/reactive_record/active_record/reactive_record/lookup_tables.rb +5 -5
  25. data/lib/reactive_record/active_record/reactive_record/operations.rb +10 -3
  26. data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +3 -0
  27. data/lib/reactive_record/active_record/reactive_record/setters.rb +108 -71
  28. data/lib/reactive_record/active_record/reactive_record/while_loading.rb +258 -41
  29. data/lib/reactive_record/broadcast.rb +62 -25
  30. data/lib/reactive_record/interval.rb +3 -3
  31. data/lib/reactive_record/permissions.rb +14 -2
  32. data/lib/reactive_record/scope_description.rb +3 -2
  33. data/lib/reactive_record/server_data_cache.rb +99 -49
  34. data/polymorph-notes.md +143 -0
  35. data/spec_fails.txt +3 -0
  36. metadata +49 -162
  37. data/Gemfile.lock +0 -431
@@ -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.
data/spec_fails.txt ADDED
@@ -0,0 +1,3 @@
1
+ rspec ./spec/batch5/save_while_loading_spec.rb:28 # save while loading with push
2
+ rspec ./spec/batch4/default_value_spec.rb:40 # defaultValue special handling will not use the defaultValue param until data is loaded - unit test
3
+ rspec ./spec/batch3/revert_spec.rb:39 # reverting records adds the todo to adam's todos and expects adam to change
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.1
4
+ version: 1.0.alpha1.6
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: 2018-11-14 00:00:00.000000000 Z
12
+ date: 2021-03-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -39,50 +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.1
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.1
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.1
48
+ version: 1.0.alpha1.6
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.1
55
+ version: 1.0.alpha1.6
70
56
  - !ruby/object:Gem::Dependency
71
- name: hyper-store
57
+ name: bundler
72
58
  requirement: !ruby/object:Gem::Requirement
73
59
  requirements:
74
- - - '='
60
+ - - ">="
75
61
  - !ruby/object:Gem::Version
76
- version: 1.0.alpha1.1
77
- type: :runtime
62
+ version: '0'
63
+ type: :development
78
64
  prerelease: false
79
65
  version_requirements: !ruby/object:Gem::Requirement
80
66
  requirements:
81
- - - '='
67
+ - - ">="
82
68
  - !ruby/object:Gem::Version
83
- version: 1.0.alpha1.1
69
+ version: '0'
84
70
  - !ruby/object:Gem::Dependency
85
- name: bundler
71
+ name: database_cleaner
86
72
  requirement: !ruby/object:Gem::Requirement
87
73
  requirements:
88
74
  - - ">="
@@ -96,7 +82,7 @@ dependencies:
96
82
  - !ruby/object:Gem::Version
97
83
  version: '0'
98
84
  - !ruby/object:Gem::Dependency
99
- name: capybara
85
+ name: factory_bot_rails
100
86
  requirement: !ruby/object:Gem::Requirement
101
87
  requirements:
102
88
  - - ">="
@@ -110,49 +96,35 @@ dependencies:
110
96
  - !ruby/object:Gem::Version
111
97
  version: '0'
112
98
  - !ruby/object:Gem::Dependency
113
- name: chromedriver-helper
99
+ name: hyper-spec
114
100
  requirement: !ruby/object:Gem::Requirement
115
101
  requirements:
116
102
  - - '='
117
103
  - !ruby/object:Gem::Version
118
- version: 1.2.0
104
+ version: 1.0.alpha1.6
119
105
  type: :development
120
106
  prerelease: false
121
107
  version_requirements: !ruby/object:Gem::Requirement
122
108
  requirements:
123
109
  - - '='
124
110
  - !ruby/object:Gem::Version
125
- version: 1.2.0
111
+ version: 1.0.alpha1.6
126
112
  - !ruby/object:Gem::Dependency
127
- name: libv8
113
+ name: hyper-trace
128
114
  requirement: !ruby/object:Gem::Requirement
129
115
  requirements:
130
- - - "~>"
116
+ - - '='
131
117
  - !ruby/object:Gem::Version
132
- version: 6.3.0
118
+ version: 1.0.alpha1.6
133
119
  type: :development
134
120
  prerelease: false
135
121
  version_requirements: !ruby/object:Gem::Requirement
136
122
  requirements:
137
- - - "~>"
123
+ - - '='
138
124
  - !ruby/object:Gem::Version
139
- version: 6.3.0
125
+ version: 1.0.alpha1.6
140
126
  - !ruby/object:Gem::Dependency
141
127
  name: mini_racer
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: 0.1.15
147
- type: :development
148
- prerelease: false
149
- version_requirements: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - "~>"
152
- - !ruby/object:Gem::Version
153
- version: 0.1.15
154
- - !ruby/object:Gem::Dependency
155
- name: selenium-webdriver
156
128
  requirement: !ruby/object:Gem::Requirement
157
129
  requirements:
158
130
  - - ">="
@@ -166,7 +138,7 @@ dependencies:
166
138
  - !ruby/object:Gem::Version
167
139
  version: '0'
168
140
  - !ruby/object:Gem::Dependency
169
- name: database_cleaner
141
+ name: pg
170
142
  requirement: !ruby/object:Gem::Requirement
171
143
  requirements:
172
144
  - - ">="
@@ -180,91 +152,27 @@ dependencies:
180
152
  - !ruby/object:Gem::Version
181
153
  version: '0'
182
154
  - !ruby/object:Gem::Dependency
183
- name: factory_bot_rails
155
+ name: opal-rails
184
156
  requirement: !ruby/object:Gem::Requirement
185
157
  requirements:
186
158
  - - ">="
187
159
  - !ruby/object:Gem::Version
188
- version: '0'
189
- type: :development
190
- prerelease: false
191
- version_requirements: !ruby/object:Gem::Requirement
192
- requirements:
193
- - - ">="
194
- - !ruby/object:Gem::Version
195
- version: '0'
196
- - !ruby/object:Gem::Dependency
197
- name: mysql2
198
- requirement: !ruby/object:Gem::Requirement
199
- requirements:
200
- - - ">="
160
+ version: 0.9.4
161
+ - - "<"
201
162
  - !ruby/object:Gem::Version
202
- version: '0'
163
+ version: '2.0'
203
164
  type: :development
204
165
  prerelease: false
205
166
  version_requirements: !ruby/object:Gem::Requirement
206
167
  requirements:
207
168
  - - ">="
208
- - !ruby/object:Gem::Version
209
- version: '0'
210
- - !ruby/object:Gem::Dependency
211
- name: opal-activesupport
212
- requirement: !ruby/object:Gem::Requirement
213
- requirements:
214
- - - "~>"
215
- - !ruby/object:Gem::Version
216
- version: 0.3.1
217
- type: :development
218
- prerelease: false
219
- version_requirements: !ruby/object:Gem::Requirement
220
- requirements:
221
- - - "~>"
222
- - !ruby/object:Gem::Version
223
- version: 0.3.1
224
- - !ruby/object:Gem::Dependency
225
- name: opal-browser
226
- requirement: !ruby/object:Gem::Requirement
227
- requirements:
228
- - - "~>"
229
- - !ruby/object:Gem::Version
230
- version: 0.2.0
231
- type: :development
232
- prerelease: false
233
- version_requirements: !ruby/object:Gem::Requirement
234
- requirements:
235
- - - "~>"
236
- - !ruby/object:Gem::Version
237
- version: 0.2.0
238
- - !ruby/object:Gem::Dependency
239
- name: opal-rails
240
- requirement: !ruby/object:Gem::Requirement
241
- requirements:
242
- - - "~>"
243
169
  - !ruby/object:Gem::Version
244
170
  version: 0.9.4
245
- type: :development
246
- prerelease: false
247
- version_requirements: !ruby/object:Gem::Requirement
248
- requirements:
249
- - - "~>"
250
- - !ruby/object:Gem::Version
251
- version: 0.9.4
252
- - !ruby/object:Gem::Dependency
253
- name: parser
254
- requirement: !ruby/object:Gem::Requirement
255
- requirements:
256
- - - ">="
257
- - !ruby/object:Gem::Version
258
- version: '0'
259
- type: :development
260
- prerelease: false
261
- version_requirements: !ruby/object:Gem::Requirement
262
- requirements:
263
- - - ">="
171
+ - - "<"
264
172
  - !ruby/object:Gem::Version
265
- version: '0'
173
+ version: '2.0'
266
174
  - !ruby/object:Gem::Dependency
267
- name: pry
175
+ name: pry-rescue
268
176
  requirement: !ruby/object:Gem::Requirement
269
177
  requirements:
270
178
  - - ">="
@@ -278,7 +186,7 @@ dependencies:
278
186
  - !ruby/object:Gem::Version
279
187
  version: '0'
280
188
  - !ruby/object:Gem::Dependency
281
- name: pry-rescue
189
+ name: pry-stack_explorer
282
190
  requirement: !ruby/object:Gem::Requirement
283
191
  requirements:
284
192
  - - ">="
@@ -339,14 +247,20 @@ dependencies:
339
247
  requirements:
340
248
  - - ">="
341
249
  - !ruby/object:Gem::Version
342
- version: 4.0.0
250
+ version: 5.0.0
251
+ - - "<"
252
+ - !ruby/object:Gem::Version
253
+ version: '7.0'
343
254
  type: :development
344
255
  prerelease: false
345
256
  version_requirements: !ruby/object:Gem::Requirement
346
257
  requirements:
347
258
  - - ">="
348
259
  - !ruby/object:Gem::Version
349
- version: 4.0.0
260
+ version: 5.0.0
261
+ - - "<"
262
+ - !ruby/object:Gem::Version
263
+ version: '7.0'
350
264
  - !ruby/object:Gem::Dependency
351
265
  name: rake
352
266
  requirement: !ruby/object:Gem::Requirement
@@ -381,20 +295,6 @@ dependencies:
381
295
  - - "<"
382
296
  - !ruby/object:Gem::Version
383
297
  version: 2.5.0
384
- - !ruby/object:Gem::Dependency
385
- name: reactrb-rails-generator
386
- requirement: !ruby/object:Gem::Requirement
387
- requirements:
388
- - - ">="
389
- - !ruby/object:Gem::Version
390
- version: '0'
391
- type: :development
392
- prerelease: false
393
- version_requirements: !ruby/object:Gem::Requirement
394
- requirements:
395
- - - ">="
396
- - !ruby/object:Gem::Version
397
- version: '0'
398
298
  - !ruby/object:Gem::Dependency
399
299
  name: rspec-collection_matchers
400
300
  requirement: !ruby/object:Gem::Requirement
@@ -539,30 +439,30 @@ dependencies:
539
439
  name: spring-commands-rspec
540
440
  requirement: !ruby/object:Gem::Requirement
541
441
  requirements:
542
- - - ">="
442
+ - - "~>"
543
443
  - !ruby/object:Gem::Version
544
- version: '0'
444
+ version: 1.0.4
545
445
  type: :development
546
446
  prerelease: false
547
447
  version_requirements: !ruby/object:Gem::Requirement
548
448
  requirements:
549
- - - ">="
449
+ - - "~>"
550
450
  - !ruby/object:Gem::Version
551
- version: '0'
451
+ version: 1.0.4
552
452
  - !ruby/object:Gem::Dependency
553
453
  name: sqlite3
554
454
  requirement: !ruby/object:Gem::Requirement
555
455
  requirements:
556
- - - ">="
456
+ - - "~>"
557
457
  - !ruby/object:Gem::Version
558
- version: '0'
458
+ version: 1.4.2
559
459
  type: :development
560
460
  prerelease: false
561
461
  version_requirements: !ruby/object:Gem::Requirement
562
462
  requirements:
563
- - - ">="
463
+ - - "~>"
564
464
  - !ruby/object:Gem::Version
565
- version: '0'
465
+ version: 1.4.2
566
466
  - !ruby/object:Gem::Dependency
567
467
  name: timecop
568
468
  requirement: !ruby/object:Gem::Requirement
@@ -577,20 +477,6 @@ dependencies:
577
477
  - - "~>"
578
478
  - !ruby/object:Gem::Version
579
479
  version: 0.8.1
580
- - !ruby/object:Gem::Dependency
581
- name: unparser
582
- requirement: !ruby/object:Gem::Requirement
583
- requirements:
584
- - - ">="
585
- - !ruby/object:Gem::Version
586
- version: '0'
587
- type: :development
588
- prerelease: false
589
- version_requirements: !ruby/object:Gem::Requirement
590
- requirements:
591
- - - ">="
592
- - !ruby/object:Gem::Version
593
- version: '0'
594
480
  description: HyperModel gives your HyperComponents CRUD access to your ActiveRecord
595
481
  models on the client, using the the standard ActiveRecord API. HyperModel also implements
596
482
  push notifications (via a number of possible technologies) so changes to records
@@ -606,7 +492,6 @@ files:
606
492
  - ".rspec"
607
493
  - ".travis.yml"
608
494
  - Gemfile
609
- - Gemfile.lock
610
495
  - Rakefile
611
496
  - bin/console
612
497
  - bin/setup
@@ -637,6 +522,7 @@ files:
637
522
  - lib/reactive_record/active_record/reactive_record/base.rb
638
523
  - lib/reactive_record/active_record/reactive_record/collection.rb
639
524
  - lib/reactive_record/active_record/reactive_record/column_types.rb
525
+ - lib/reactive_record/active_record/reactive_record/dummy_polymorph.rb
640
526
  - lib/reactive_record/active_record/reactive_record/dummy_value.rb
641
527
  - lib/reactive_record/active_record/reactive_record/getters.rb
642
528
  - lib/reactive_record/active_record/reactive_record/isomorphic_base.rb
@@ -656,6 +542,8 @@ files:
656
542
  - lib/reactive_record/scope_description.rb
657
543
  - lib/reactive_record/serializers.rb
658
544
  - lib/reactive_record/server_data_cache.rb
545
+ - polymorph-notes.md
546
+ - spec_fails.txt
659
547
  homepage: http://ruby-hyperstack.org
660
548
  licenses:
661
549
  - MIT
@@ -675,8 +563,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
675
563
  - !ruby/object:Gem::Version
676
564
  version: 1.3.1
677
565
  requirements: []
678
- rubyforge_project:
679
- rubygems_version: 2.7.8
566
+ rubygems_version: 3.0.8
680
567
  signing_key:
681
568
  specification_version: 4
682
569
  summary: React based CRUD access and Synchronization of active record models across