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