Skip to content

Is there any way to pass arguments to a relationship resource? #110

Open
@connor-odoherty

Description

@connor-odoherty

Let's say we have a model Professor.rb that is serialized by the SerializableProfessor. The professor has the attributes:

  • name
  • age
  • phone_number

In certain cases, depending on the class (or even higher up the chain, depending on the Student who has_many Lectures, which has_one Professor), I want to be able to return the phone_number as itself, or as nil.

In this contrived example, the Professor model does not know anything about Lectures. A Lecture has_one Professor, but the Professor DOES NOT have_many Lectures.

Is there any way to tell SerializableProfessor whether or not to show the phone_number from SerializableLecture?

Ideally, SerializableLecture would look like so:

class SerializableLecture < ApplicationSerializer
  ...
  ...
  has_one :professor do
    data do
      @object.professor
    end
    arguments do
      { show_phone_number: false }
    end
  end
end

and SerializableProfessor could do:

class SerializableProfessor < ApplicationSerializer
    extend JSONAPI::Serializable::Resource::ConditionalFields

   attribute :phone_number, unless -> { @arguments[:phone_number] }
end

OR

Even better, we could conditionally decide which Serializer to use. Maybe we have a base SerializableProfessor, and we have SerializableProfessorWithContactInfo and SerializableProfessorWithoutContactInfo. Then, we do something like:

class SerializableLecture < ApplicationSerializer
  ...
  ...
  has_one :professor do
    data do
      @object.professor
    end
    serializer_to_use do
      @object.is_a_lecture_with_contact_info? ? SerializableProfessorWithContactInfo : SerializableProfessorWithoutContactInfo
    end
  end
end

While I could use expose define a mapping of Professor UUIDs to whether or not I should be returning contact info, this could become performance costly at a large scale, non-contrived scenario.

Beyond what I have proposed, are there any other ways to achieve that desired behavior?

Additionally, if I can't do anything from the relationship perspective, is there any way to access the serialization capabilities of a single Serializable resource class? That way, instead of defining a has_one, I could do:

class SerializableLecture < ApplicationSerializer
  ...
  ...
  attribute :professor do
    serialized_professor = SerializableProfessor.new(@object.professor)
    serialized_professor[:phone_number] = @object.is_a_lecture_with_contact_info? ? @object.professor.phone_number : nil
    serialized_professor
  end
end

I understand that the issue here is: 'What happens if Professor A when referenced from Lecture A is supposed to show phone_number, but when referenced from Lecture B, they are not supposed to return phone_number?'. Maybe we can keep track of all arguments passed on a resource to resource level, and then allow the resource itself to determine what to do with those collected arguments?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions