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

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