Skip to content

Commit 6c4382c

Browse files
committed
spec is passing
1 parent bff7bc7 commit 6c4382c

5 files changed

Lines changed: 108 additions & 9 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def self.reflect_on_association(attr)
1111
end
1212

1313
def self.reflect_on_association_by_foreign_key(key)
14-
reflection_finder { |assoc| assoc.association_foreign_key == key }
14+
reflection_finder { |assoc| assoc.association_foreign_key == key && assoc.macro != :has_many }
1515
end
1616

1717
def self.reflection_finder(&block)
@@ -161,6 +161,7 @@ def inverse_of(model = nil)
161161
def find_inverse(model) # private
162162
the_klass = klass(model)
163163
the_klass.reflect_on_all_associations.each do |association|
164+
next if association == self
164165
next if association.association_foreign_key != @association_foreign_key
165166
next if association.attribute == attribute
166167
return association if association.polymorphic? || association.klass == owner_class

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ def _react_param_conversion(param, opt = nil)
384384
klass = ReactiveRecord::Base.infer_type_from_hash(self, param)
385385
klass == self || klass < self
386386
else
387+
#debugger if param[:duplicate_of_id]
387388
# TODO: investigate saving .changes here and then replacing the
388389
# TODO: changes after the load is complete. In other words preserve the
389390
# TODO: changed values as changes while just updating the synced values.
@@ -415,7 +416,7 @@ def _react_param_conversion(param, opt = nil)
415416
if key == poly_assoc.polymorphic_type_attribute
416417
model_name = value
417418
already_processed_keys << poly_assoc.association_foreign_key
418-
elsif key == poly_assoc.association_foreign_key # && poly_assoc.polymorphic_type_attribute #poly_assoc.macro != :has_many
419+
elsif key == poly_assoc.association_foreign_key && (poly_assoc.polymorphic_type_attribute || poly_assoc.macro == :belongs_to)
419420
model_id = value
420421
already_processed_keys << poly_assoc.polymorphic_type_attribute
421422
end

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,8 @@ def internal_replace(new_array)
558558
end
559559

560560
def delete(item)
561-
unsaved_children.delete(item)
562-
notify_of_change(
561+
Hyperstack::Internal::State::Mapper.bulk_update do
562+
unsaved_children.delete(item)
563563
if @owner && @association
564564
inverse_of = @association.inverse_of
565565
if (backing_record = item.backing_record) && item.attributes[inverse_of] == @owner && !@association.through_association?
@@ -569,8 +569,8 @@ def delete(item)
569569
delete_internal(item) { @owner.backing_record.sync_has_many(@association.attribute) }
570570
else
571571
delete_internal(item)
572-
end
573-
)
572+
end.tap { Hyperstack::Internal::State::Variable.set(self, :collection, collection) }
573+
end
574574
end
575575

576576
def delete_internal(item)

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,15 @@ def self.load_from_json(tree, target = nil)
492492

493493
target.send "#{method}=", value.first
494494
elsif value.is_a? Array
495-
# we cannot use target.send "#{method}=" here because it might be a server method, which does not have a setter
496-
# a better fix might be something like target._internal_attribute_hash[method] = ...
497-
target.backing_record.set_attr_value(method, value.first) unless method == :id
495+
unless method == :id
496+
# we cannot always use target.send "#{method}=" here because it might be a server method, which does not have a setter
497+
# a better fix might be something like target._internal_attribute_hash[method] = ...
498+
if target.respond_to?("#{method}=")
499+
target.send("#{method}=", value.first)
500+
else
501+
target.backing_record.set_attr_value(method, value.first) unless method == :id
502+
end
503+
end
498504
elsif value.is_a?(Hash) && value[:id] && value[:id].first && (association = target.class.reflect_on_association(method))
499505
# 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?
500506
klass = value[:model_name] ? Object.const_get(value[:model_name].first) : association.klass
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
require 'spec_helper'
2+
describe "self referencing belongs_to", js: true do
3+
4+
before(:all) do
5+
require 'pusher'
6+
require 'pusher-fake'
7+
Pusher.app_id = "MY_TEST_ID"
8+
Pusher.key = "MY_TEST_KEY"
9+
Pusher.secret = "MY_TEST_SECRET"
10+
require "pusher-fake/support/base"
11+
12+
Hyperstack.configuration do |config|
13+
config.transport = :pusher
14+
config.channel_prefix = "synchromesh"
15+
config.opts = {app_id: Pusher.app_id, key: Pusher.key, secret: Pusher.secret}.merge(PusherFake.configuration.web_options)
16+
end
17+
end
18+
19+
before(:all) do
20+
class ActiveRecord::Base
21+
class << self
22+
def public_columns_hash
23+
@public_columns_hash ||= {}
24+
end
25+
end
26+
end
27+
28+
class SelfRefModel < ActiveRecord::Base
29+
def self.build_tables
30+
connection.create_table :self_ref_models, force: true do |t|
31+
t.string :name
32+
t.string :other
33+
t.belongs_to :parent
34+
t.timestamps
35+
end
36+
ActiveRecord::Base.public_columns_hash[name] = columns_hash
37+
end
38+
end
39+
40+
SelfRefModel.build_tables
41+
end
42+
43+
before(:each) do
44+
45+
stub_const 'TestApplication', Class.new
46+
stub_const 'TestApplicationPolicy', Class.new
47+
48+
TestApplicationPolicy.class_eval do
49+
always_allow_connection
50+
regulate_all_broadcasts { |policy| policy.send_all }
51+
end
52+
53+
isomorphic do
54+
class SelfRefModel < ActiveRecord::Base
55+
# the failure is caused by the has_many relationship coming first...
56+
has_many :children, class_name: 'SelfRefModel', foreign_key: 'parent_id'
57+
belongs_to :parent, class_name: 'SelfRefModel', required: false
58+
end
59+
end
60+
61+
SelfRefModel.create(name: 'first model')
62+
SelfRefModel.create(name: 'second model')
63+
64+
mount 'SelfRefModelIndex' do
65+
class SelfRefModelIndex < HyperComponent
66+
render(UL) do
67+
SelfRefModel.first.tap do |m|
68+
if m.parent&.id
69+
LI { "name: #{m.name}, parent id: #{m.parent.id}." }
70+
elsif !m.children.empty?
71+
LI { "name: #{m.name}, children: [#{m.children.collect(&:id)}]"}
72+
else
73+
LI { "name: #{m.name}." }
74+
end
75+
end
76+
end
77+
end
78+
end
79+
80+
size_window(:small, :portrait)
81+
end
82+
83+
it 'will be updated properly' do
84+
SelfRefModel.last.update(parent: SelfRefModel.first)
85+
expect(page).to have_content('name: first model, children: [2]')
86+
SelfRefModel.last.update(parent: nil)
87+
expect(page).to have_content('name: first model.')
88+
SelfRefModel.first.update(parent: SelfRefModel.last)
89+
expect(page).to have_content('name: first model, parent id: 2.')
90+
end
91+
end

0 commit comments

Comments
 (0)