fast_jsonapi icon indicating copy to clipboard operation
fast_jsonapi copied to clipboard

Set the serializer with polymorphic association

Open johnvuko opened this issue 6 years ago • 9 comments

Hi, I would like to know if if is possible to force the serializer with polymorphic relation? The problem is I used namespace.

I have a 3 models:

  • Product::Product
  • Receipt::Receipt
  • Receipt::Ingredient

each one has it's own serializer:

  • Product::ProductSerializer
  • Receipt::ReceiptSerializer
  • Receipt::IngredientSerializer

A ``Receipt::Ingredienthave anitemwhich can be either aProduct::ProductorReceipt::Receipt`.

The code of my model Receipt::Ingredient:

class Receipt::Ingredient < ApplicationRecord
  belongs_to :item, polymorphic: true
end

The code of my serializer Receipt::IngredientSerializer:

module Receipt
  class IngredientSerializer
    include FastJsonapi::ObjectSerializer

    belongs_to :item, polymorphic: true

  end
end

When I try to serialize I have an exception NameError (uninitialized constant Receipt::ProductSerializer).

johnvuko avatar Dec 28 '18 17:12 johnvuko

NameError (uninitialized constant Receipt::ProductSerializer)

If that's not a typo then this is your problem. You don't have a Receipt::ProductSerializer. You have a Product::ProductSerializer. To be honest using namespaces that have the same names a classes is gonna cause you problems and you're probably not correctly abstracting things with names like that.

PhilT avatar Dec 30 '18 21:12 PhilT

It's not a typo problem and the fact my class has the same name as my namespace doesn't change anything, I could rename it the problem stay the same.

johnvuko avatar Dec 30 '18 21:12 johnvuko

Yes I've just been looking closer and I see your problem now

PhilT avatar Dec 30 '18 21:12 PhilT

Is the type field in the model being saved correctly with the namespace?

PhilT avatar Dec 30 '18 21:12 PhilT

What do you mean? The polymorphic relation work without problem with Rails without doing anything else than belongs_to :item, polymorphic: true and in database I have to correct class with the namespace like Product::Prodcut.

johnvuko avatar Dec 30 '18 21:12 johnvuko

In that case it's possibly an issue with fast_jsonapi. As a workaround you may be able to do something like ProductSerializer = Product::ProductSerializer inside the IngredientSerializer or even define it in the module.

PhilT avatar Dec 30 '18 21:12 PhilT

Thanks, that's what I did for now but that's a big hack. I expect more something like an option serializer for polymorphic association like we can define the record_type.

johnvuko avatar Dec 30 '18 21:12 johnvuko

I'm having a similar issue! I'm using ActiveStorage and want to serialize ActiveStorage::Attachment objects with my AttachmentSerializer which has no prefixed modules.

In my NewsPostSerializer, has_many works! (It helps that my association name gives away the needed serializer and there are no modules)

has_many :attachments, polymorphic: true, if: Proc.new { |post| post.attachments.attached? }

But in my DlsClass::GroupSerializer, has_one is a pain. The following will make "type": "one" because ActiveStorage wraps it in an Attached::One object with delegation.

has_one :orientation_pdf, polymorphic: true, if: Proc.new { |group| group.orientation_pdf.attached? }

I solved this by applying a block and directly returning the attachment

has_one :orientation_pdf, polymorphic: true, if: Proc.new { |group| group.orientation_pdf.attached? } do |group|
  group.orientation_pdf.attachment
end

but because the group serializer is in a module DlsClass::GroupSerializer, it is trying to find a serializer DlsClass::AttachmentSerializer and even though in the end I tried explicitly stating the serializer option, this thread makes me think your project is ignoring it because it is a polymorphic association.

has_one :orientation_pdf,
        serializer: AttachmentSerializer,
        polymorphic: true,
        if: Proc.new { |group| group.orientation_pdf.attached? } do |group|
    group.orientation_pdf.attachment
end

So this module guessing for a polymorphic association is a major problem.

leehericks avatar Feb 17 '20 01:02 leehericks

Well, in fact because this association is not polymorphic I was wrong. I fixed everything:

class DlsClass::GroupSerializer
  include FastJsonapi::ObjectSerializer

  has_one :orientation_pdf,
          record_type: :attachment,
          serializer: AttachmentSerializer,
          if: Proc.new { |group| group.orientation_pdf.attached? } do |group|
    group.orientation_pdf.attachment
  end
end

I guess if you were on the ActiveStorage::Attachment side and wanted to serialize the polymorphic record (record_type, record_id, name) then this would be applicable if modules were involved.

leehericks avatar Feb 17 '20 01:02 leehericks