Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble detecting polymorphic relations #65

Open
oyeanuj opened this issue Feb 14, 2020 · 6 comments
Open

Trouble detecting polymorphic relations #65

oyeanuj opened this issue Feb 14, 2020 · 6 comments

Comments

@oyeanuj
Copy link
Contributor

oyeanuj commented Feb 14, 2020

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:

class DrinkSerializer < Panko::Serializer
  has_one :drinkable
  # Since it belongs to either Tea or Coffee, I can't use 'serializer: option'
  # AMS detected it automatically, so how do I tell Panko which one to use? 
end

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!

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Feb 14, 2020

Ideally, Panko can determine it, or it can provide an option like fast_jsonapi folks provide:

has_many :targets, polymorphic: { Person => :person, Group => :group }

@yosiat
Copy link
Owner

yosiat commented Feb 14, 2020

@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?

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Feb 14, 2020

@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.

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Feb 14, 2020

@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

@irondnb
Copy link

irondnb commented Feb 14, 2020

@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

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Feb 15, 2020

@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 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants