Skip to content

Commit 30cb366

Browse files
committed
wip - some specs passing
1 parent ee3ee7e commit 30cb366

File tree

12 files changed

+516
-127
lines changed

12 files changed

+516
-127
lines changed

.travis.yml

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -54,52 +54,52 @@ _deploy_gem: &_deploy_gem
5454

5555
jobs:
5656
include:
57-
- <<: *_test_gem
58-
env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1
59-
- <<: *_test_gem
60-
env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1
61-
- <<: *_test_gem
62-
env: COMPONENT=hyper-state RUBY_VERSION=2.5.1
63-
- <<: *_test_gem
64-
env: COMPONENT=hyper-component RUBY_VERSION=2.5.1
57+
# - <<: *_test_gem
58+
# env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1
59+
# - <<: *_test_gem
60+
# env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1
61+
# - <<: *_test_gem
62+
# env: COMPONENT=hyper-state RUBY_VERSION=2.5.1
63+
# - <<: *_test_gem
64+
# env: COMPONENT=hyper-component RUBY_VERSION=2.5.1
6565
- <<: *_test_gem
6666
env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part1
6767
- <<: *_test_gem
6868
env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part2
6969
- <<: *_test_gem
7070
env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part3
71-
- <<: *_test_gem
72-
env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1
73-
- <<: *_test_gem
74-
env: COMPONENT=hyper-router RUBY_VERSION=2.5.1
75-
- <<: *_test_gem
76-
env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1
77-
- <<: *_test_gem
78-
env: COMPONENT=hyper-store RUBY_VERSION=2.5.1
79-
- <<: *_test_gem
80-
env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1
81-
- <<: *_test_gem
82-
env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1
83-
84-
- <<: *_deploy_gem
85-
env: COMPONENT=hyper-i18n
86-
- <<: *_deploy_gem
87-
env: COMPONENT=hyper-trace
88-
- <<: *_deploy_gem
89-
env: COMPONENT=hyper-state
90-
- <<: *_deploy_gem
91-
env: COMPONENT=hyper-component
92-
- <<: *_deploy_gem
93-
env: COMPONENT=hyper-model
94-
- <<: *_deploy_gem
95-
env: COMPONENT=hyper-operation
96-
- <<: *_deploy_gem
97-
env: COMPONENT=hyper-router
98-
- <<: *_deploy_gem
99-
env: COMPONENT=hyper-spec
100-
- <<: *_deploy_gem
101-
env: COMPONENT=hyper-store
102-
- <<: *_deploy_gem
103-
env: COMPONENT=rails-hyperstack
104-
- <<: *_deploy_gem
105-
env: COMPONENT=hyperstack-config
71+
# - <<: *_test_gem
72+
# env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1
73+
# - <<: *_test_gem
74+
# env: COMPONENT=hyper-router RUBY_VERSION=2.5.1
75+
# - <<: *_test_gem
76+
# env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1
77+
# - <<: *_test_gem
78+
# env: COMPONENT=hyper-store RUBY_VERSION=2.5.1
79+
# - <<: *_test_gem
80+
# env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1
81+
# - <<: *_test_gem
82+
# env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1
83+
#
84+
# - <<: *_deploy_gem
85+
# env: COMPONENT=hyper-i18n
86+
# - <<: *_deploy_gem
87+
# env: COMPONENT=hyper-trace
88+
# - <<: *_deploy_gem
89+
# env: COMPONENT=hyper-state
90+
# - <<: *_deploy_gem
91+
# env: COMPONENT=hyper-component
92+
# - <<: *_deploy_gem
93+
# env: COMPONENT=hyper-model
94+
# - <<: *_deploy_gem
95+
# env: COMPONENT=hyper-operation
96+
# - <<: *_deploy_gem
97+
# env: COMPONENT=hyper-router
98+
# - <<: *_deploy_gem
99+
# env: COMPONENT=hyper-spec
100+
# - <<: *_deploy_gem
101+
# env: COMPONENT=hyper-store
102+
# - <<: *_deploy_gem
103+
# env: COMPONENT=rails-hyperstack
104+
# - <<: *_deploy_gem
105+
# env: COMPONENT=hyperstack-config

ruby/hyper-model/lib/hyper-model.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
require "reactive_record/active_record/reactive_record/isomorphic_base"
2121
require 'reactive_record/active_record/reactive_record/dummy_value'
2222
require 'reactive_record/active_record/reactive_record/column_types'
23+
require 'reactive_record/active_record/reactive_record/dummy_polymorph'
2324
require "reactive_record/active_record/aggregations"
2425
require "reactive_record/active_record/associations"
2526
require "reactive_record/active_record/reactive_record/backing_record_inspector"

ruby/hyper-model/lib/reactive_record/active_record/associations.rb

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class AssociationReflection
3838
attr_reader :macro
3939
attr_reader :owner_class
4040
attr_reader :source
41+
attr_reader :source_type
4142
attr_reader :options
4243

4344
def initialize(owner_class, macro, name, options = {})
@@ -49,10 +50,26 @@ def initialize(owner_class, macro, name, options = {})
4950
@klass_name = options[:class_name] || (collection? && name.camelize.singularize) || name.camelize
5051
end
5152
@association_foreign_key =
52-
options[:foreign_key] || (macro == :belongs_to && "#{name}_id") ||
53-
(options[:as] && "#{options[:as]}_id") || "#{@owner_class.name.underscore}_id"
54-
@source = options[:source] || @klass_name.underscore if options[:through]
53+
options[:foreign_key] ||
54+
(macro == :belongs_to && "#{name}_id") ||
55+
(options[:as] && "#{options[:as]}_id") ||
56+
(options[:polymorphic] && "#{name}_id") ||
57+
"#{@owner_class.name.underscore}_id"
58+
if options[:through]
59+
@source = options[:source] || @klass_name.underscore
60+
@source_type = options[:source_type] || @klass_name
61+
end
5562
@attribute = name
63+
@through_associations = Hash.new { |_h, k| [] unless k }
64+
@source_associations = Hash.new { |_h, k| [] unless k }
65+
end
66+
67+
def collection?
68+
@macro == :has_many
69+
end
70+
71+
def singular?
72+
@macro != :has_many
5673
end
5774

5875
def through_association
@@ -67,21 +84,23 @@ def through_association
6784

6885
alias through_association? through_association
6986

70-
def through_associations
87+
def through_associations(model)
7188
# find all associations that use the inverse association as the through association
7289
# that is find all associations that are using this association in a through relationship
73-
@through_associations ||= klass.reflect_on_all_associations.select do |assoc|
74-
assoc.through_association && assoc.inverse == self
90+
the_klass = klass(model)
91+
@through_associations[the_klass] ||= the_klass.reflect_on_all_associations.select do |assoc|
92+
assoc.through_association && assoc.inverse(nil) == self
7593
end
7694
end
7795

78-
def source_associations
96+
def source_associations(model)
7997
# find all associations that use this association as the source
80-
# that is final all associations that are using this association as the source in a
98+
# that is find all associations that are using this association as the source in a
8199
# through relationship
82-
@source_associations ||= owner_class.reflect_on_all_associations.collect do |sibling|
83-
sibling.klass.reflect_on_all_associations.select do |assoc|
84-
assoc.source == attribute
100+
the_klass = klass(model)
101+
@source_associations[the_klass] ||= owner_class.reflect_on_all_associations.collect do |sibling|
102+
sibling.klass(model).reflect_on_all_associations.select do |assoc|
103+
assoc.source == attribute && assoc.source_type == the_klass.name
85104
end
86105
end.flatten
87106
end
@@ -92,25 +111,25 @@ def polymorphic?
92111

93112
def inverse(model)
94113
return @inverse if @inverse
95-
found = through_association ? through_association.inverse(model) : find_inverse(model)
114+
ta = through_association(model)
115+
found = ta ? ta.inverse(model) : find_inverse(model)
96116
@inverse = found unless polymorphic?
97117
found
98118
end
99119

100120
def inverse_of(model = nil)
101-
inverse(model)&.attribute
121+
inverse(model).attribute
102122
end
103123

104124
def find_inverse(model) # private
105-
the_klass = klass || model
106-
return nil unless the_klass
125+
the_klass = klass(model)
107126
the_klass.reflect_on_all_associations.each do |association|
108127
next if association.association_foreign_key != @association_foreign_key
109-
next unless target_klass_matches(association)
110128
next if association.attribute == attribute
111129
return association if the_klass == association.owner_class
112130
end
113-
return if options[:polymorphic] # can't dynamically create the polymorphic has_many
131+
debugger if options[:polymorphic]
132+
raise "could not find inverse of polymorphic belongs_to: #{model.inspect} #{self.inspect}" if options[:polymorphic]
114133
# instead of raising an error go ahead and create the inverse relationship if it does not exist.
115134
# https://github.com/hyperstack-org/hyperstack/issues/89
116135
if macro == :belongs_to
@@ -125,22 +144,17 @@ def find_inverse(model) # private
125144
end
126145
end
127146

128-
def klass
147+
def klass(model = nil)
129148
@klass ||= Object.const_get(@klass_name) if @klass_name
130-
end
131-
132-
def target_klass_matches?(inverse_association)
133-
return inverse_association.options[:as] if options[:polymorphic]
134-
@owner_class == inverse_association.klass
149+
raise "model is not correct class" if @klass && model && model.class != @klass
150+
debugger unless @klass || model
151+
raise "no model supplied for polymorphic relationship" unless @klass || model
152+
@klass || model.class
135153
end
136154

137155
def collection?
138156
[:has_many].include? @macro
139157
end
140-
141158
end
142-
143159
end
144-
145-
146160
end

ruby/hyper-model/lib/reactive_record/active_record/class_methods.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,20 @@ def _react_param_conversion(param, opt = nil)
383383
end
384384

385385
if assoc
386-
if value
387-
[assoc.attribute, { id: [value] }]
388-
else
386+
if !value
389387
[assoc.attribute, [nil]]
388+
elsif assoc.polymorphic?
389+
model_name = param.detect { |k, *| k == "#{assoc.attribute}_type" }&.last
390+
model_name ||= target.send("#{assoc.attribute}_type")
391+
unless Object.const_defined?(model_name)
392+
raise "Error in #{self.name}._react_param_conversion. \n"\
393+
"Could not determine the type of #{assoc.attribute} of #{target.inspect}.\n"\
394+
"It was not provided in the conversion data, "\
395+
"and it is unknown on the client"
396+
end
397+
[assoc.attribute, { id: [value], model_name: [model_name] }]
398+
else
399+
[assoc.attribute, { id: [value]}]
390400
end
391401
else
392402
[key, [value]]

ruby/hyper-model/lib/reactive_record/active_record/reactive_record/base.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ def self.new_from_vector(model, aggregate_owner, *vector)
115115
# this is the equivilent of find but for associations and aggregations
116116
# because we are not fetching a specific attribute yet, there is NO communication with the
117117
# server. That only happens during find.
118+
119+
return DummyPolymorph.new(vector) unless model
120+
118121
model = model.base_class
119122

120123
# do we already have a record with this vector? If so return it, otherwise make a new one.

ruby/hyper-model/lib/reactive_record/active_record/reactive_record/collection.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,15 @@ def update_child(item)
416416
backing_record = item.backing_record
417417
if backing_record && @owner && @association && !@association.through_association? && item.attributes[@association.inverse_of] != @owner
418418
inverse_of = @association.inverse_of
419-
current_association = item.attributes[inverse_of]
419+
current_association_value = item.attributes[inverse_of]
420420
backing_record.virgin = false unless backing_record.data_loading?
421421
backing_record.update_belongs_to(inverse_of, @owner)
422-
if current_association && current_association.attributes[@association.attribute]
423-
current_association.attributes[@association.attribute].delete(item)
422+
unless current_association_value.nil? # might be a dummy value which responds to nil
423+
current_association = @association.inverse.inverse(current_association_value)
424+
current_association_attribute = current_association.attribute
425+
if current_association.collection? && current_association_value.attributes[current_association_attribute]
426+
current_association.attributes[current_association_attribute].delete(item)
427+
end
424428
end
425429
@owner.backing_record.sync_has_many(@association.attribute)
426430
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module ReactiveRecord
2+
class DummyPolymorph
3+
def initialize(vector)
4+
@vector = vector
5+
puts "VECTOR: #{@vector.inspect}"
6+
Base.load_from_db(nil, *vector, 'id')
7+
Base.load_from_db(nil, *vector, 'model_name')
8+
end
9+
10+
def nil?
11+
true
12+
end
13+
14+
def method_missing(*)
15+
self
16+
end
17+
18+
def self.reflect_on_all_associations(*)
19+
[]
20+
end
21+
end
22+
end

ruby/hyper-model/lib/reactive_record/active_record/reactive_record/getters.rb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ module Getters
55
def get_belongs_to(assoc, reload = nil)
66
getter_common(assoc.attribute, reload) do |has_key, attr|
77
return if new?
8-
value = Base.fetch_from_db([@model, [:find, id], attr, @model.primary_key]) if id.present?
9-
value = find_association(assoc, value)
8+
if id.present?
9+
value = Base.fetch_from_db([@model, [:find, id], attr, @model.primary_key])
10+
klass = Base.fetch_from_db([@model, [:find, id], attr, 'class', 'name'])
11+
klass &&= Object.const_get(klass)
12+
end
13+
value = find_association(assoc, value, klass)
1014
sync_ignore_dummy attr, value, has_key
1115
end&.cast_to_current_sti_type
1216
end
@@ -102,13 +106,16 @@ def getter_common(attribute, reload)
102106
end.tap { |value| Hyperstack::Internal::State::Variable.get(self, attribute) unless data_loading? }
103107
end
104108

105-
def find_association(association, id)
106-
inverse_of = association.inverse_of
109+
def find_association(association, id, klass)
107110
instance = if id
108-
find(association.klass, association.klass.primary_key => id)
111+
find(klass, klass.primary_key => id)
112+
elsif association.polymorphic?
113+
new_from_vector(nil, nil, *vector, association.attribute)
109114
else
110115
new_from_vector(association.klass, nil, *vector, association.attribute)
111116
end
117+
return instance if instance.is_a? DummyPolymorph
118+
inverse_of = association.inverse_of(instance)
112119
instance_backing_record_attributes = instance.attributes
113120
inverse_association = association.klass.reflect_on_association(inverse_of)
114121
if inverse_association.collection?

ruby/hyper-model/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def self.gather_records(records_to_process, force, record_being_saved)
223223
if association.collection?
224224
# following line changed from .all to .collection on 10/28
225225
[*value.collection, *value.unsaved_children].each do |assoc|
226-
add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of) or assoc.new?
226+
add_new_association.call(record, attribute, assoc.backing_record) if assoc.changed?(association.inverse_of(assoc)) or assoc.new?
227227
end
228228
elsif record.new? || record.changed?(attribute) || (record == record_being_saved && force)
229229
if value.nil?

0 commit comments

Comments
 (0)