Open oyeanuj opened 4 years ago
Ideally, Panko can determine it, or it can provide an option like fast_jsonapi folks provide:
has_many :targets, polymorphic: { Person => :person, Group => :group }
@oyeanuj when panko handles associations it's simple as calling a method on the subject, for example drink.drinkable
so there is no something special there.
If you can provide me with an example with this template - https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_gem.rb I could find out the root cause and create a PR to fix it.
EDIT:
Now I understand your issue here, the problem is the relation is polymorphic and you don't know which serializer to use?
@yosiat: I think I can clarify - the issue is that the polymorphic relationships aren't being discovered by Panko even though ActiveRecord knows more. So drink.drinkable
is leading to a result but Panko throws a runtime error saying there is no serializer for it.
My guess is it is looking for a DrinkableSerializer rather than treating them as polymorphic? If it is hard for Panko to tell, then an option like in Fast_JsonAPI above would be helpful.
@yosiat I wasn't sure how to create a test case for Panko from that template but I did make a template with a polymorphic relation which almost gets us there. Here it is and hope this is helpful:
https://gist.github.com/oyeanuj/b10cc51de54239543d21a66dcf9a4b39
@oyeanuj Like @yosiat said, you can just calls a method defined in each polymorphic model.
class MembershipSerializer < Panko::Serializer
attributes :id, :identity, :created_at, :updated_at
def identity
object.identity.serialize(
except: [:updated_at, :created_at]
)
end
end
class Membership < ApplicationRecord
belongs_to :identity, polymorphic: true
end
class Guest < ApplicationRecord
has_many :memberships, as: :identity, dependent: :destroy
def serialize(options={})
GuestSerializer.new(options).serialize(self)
end
end
class User < ApplicationRecord
has_many :memberships, as: :identity, dependent: :destroy
def serialize(options={})
UserSerializer.new(options).serialize(self)
end
end
or you can simply create module for reuse.
module Serializable
def serialize(options={})
serializer = options[:serializer] || serializer_class_name
serializer.new(options).serialize(self)
end
private
def serializer_class_name
"#{self.class.name}Serializer".constantize
rescue NameError => e
raise "Missing #{self.class.name} serializer."
end
end
@irondnb thanks for that helpful example! I think it can certainly be done in the userland but I think it feels weird that it is inconsistent with how other has_one
and has_many
relations work automagically within a serializer and polymorphic ones don't seem to be. If the inference here works, then they will end up behaving consistently with other relations which would be amazing :)
Hi @yosiat, As I was migrating from AMS to this excellent serializer, I keep running into an error where Panko is unable to determine the serializer for a polymorphic relation:
I couldn't find polymorphic relations mentioned in the docs, so let me know the best way to work with polymorphic relations in Panko.
Thank you!