Open sfcgeorge opened 7 years ago
I've found 2 places in the code where the class is changing to the superclass.
https://github.com/ruby-hyperloop/hyper-mesh/blob/5e811858548f31a73a33e3e856e65c97b57c20e8/lib/reactive_record/active_record/class_methods.rb#L45 Instance eval changes self so you're not passing in the self you might think. Easy fix:
def find(id)
base_class.instance_eval {ReactiveRecord::Base.find(self, primary_key, id)}
end
I assume there's a reason why base_class
is used all over the place. But it does what it says and gives you the superclass so you loose access to the methods in the actual model you're trying to use. I don't see why base_class
is necessary at all, as with inheritance all the superclass methods are available in the child. And if you're able to call base_class
then you must have inherited from Base so there's no point checking this condition.
Maybe there's another kind of AR internals object that you can end up with where it's necessary to call superclass to get something useful? But checking for those edge cases might be better than always calling base_class
.
Redefining base class to return self seems to work fine. Async loading and saving on the client works in STI models.
Commenting out model = model.base_class
has the same effect as redefining it. So if there are places when base_class
is actually needed to do it's thing then they could be left in and everywhere else removed.
Without the base_class
fix the model is initially memoized as User
and then the server correctly returns Employer
but it's never updated. Changing this to a regular assignment updates the class correctly but doesn't help with the initial page load and is probably undesirable for caching reasons.
The below patch got STI models working correctly for me. The model starts of as Employer
and stays that way. So far it doesn't seem to have broken anything else but probably has as I don't know what the reason behind base_class
really is.
if RUBY_ENGINE == "opal"
module ActiveRecord
module ClassMethods
def base_class
unless self < Base
raise ActiveRecordError, "#{name} doesn't descend from ActiveRecord"
end
if superclass == Base || superclass.abstract_class?
self
elsif respond_to?(:each)
superclass.base_class
else
self
end
end
def find(id)
clss = self # instance_eval changes self
base_class.instance_eval do
ReactiveRecord::Base.find(clss, primary_key, id)
end
end
end
end
end
If single table inheritance is used on the back end, hyper-mesh won't instantiate the correct subclass, only ever the parent class.
The AR method
becomes
should also be added to allow switching class:Basically Rails always automatically converts into the most specific STI sub-class.
Fairly sure this will fix #38 too