Description
In an application I'm working on, we had an issue where we had a model with a polymorphic belongs to association, that used different resource subclasses based on the type of the association.
For the basic index
, show
, etc. actions this worked fine (you can override resource_type_for
or use model hints), but when we tried to access one of these models using a get_related_resource
route, we found that it used the superclass resource.
This seems to be because of this method in resource.rb:
define_method relationship_name do |options = {}|
relationship = self.class._relationships[relationship_name]
if relationship.polymorphic?
associated_model = public_send(associated_records_method_name)
resource_klass = self.class.resource_for_model(associated_model) if associated_model
return resource_klass.new(associated_model, @context) if resource_klass
else
resource_klass = relationship.resource_klass
if resource_klass
associated_model = public_send(associated_records_method_name)
return associated_model ? resource_klass.new(associated_model, @context) : nil
end
end
end unless method_defined?(relationship_name)
Using relationship.resource_klass
looks up the resource class using the class of the model, which doesn't allow for the resource class to be changed based on attributes of the model. At this point, the model instance is known, so it should be possible to adapt it to look up the resource class based on the model instance instead of the model class.
Currently, we're getting around this by overriding .new
on the superclass relationship like this, but it's pretty hacky:
def self.new(model, *args)
return super if self < V1::QuestionResource || model.content_type.nil?
resource_for_model(model).new(model, *args)
end
Is this something there'd be interest in changing?