Using inheritance, first you can clean up your structure as following:
class DepartmentNameSerializer < Serializer
self.root = false
attributes :id, :name
end
class DepartmentSerializer < DepartmentNameSerializer
has_many :employees, serializer: EmployeeSerializer
has_one :location, serializer: LocationNameSerializer
end
class DepartmentWithManagersSerializer < DepartmentNameSerializer
has_many :primary_managers, serializer: ManagerSerializer
has_many :secondary_managers, serializer: ManagerSerializer
end
class DepartmentWithEmployeesSerializer < DepartmentNameSerializer
has_many :employees, serializer: EmployeeNameSerializer
end
There is little you can do to really enhance your code any further in terms of readability and reusability if you want to separate all serializer contexts into separate classes like this.
If you are using ActiveModel::Serializers
which I think you do, since 0.8.0
you can use ActiveRecord
-Serialization-like :except
and :only
to add some serialization context, so you could refactor your structure to work like the following:
class DepartmentSerializer < Serializer
self.root = false
attributes :id, :name, :employee_names, :location_names
# it is afaik not possible to pass serialization context to the other serializers
# via association
# has_many :employee_names, serializer: EmployeeSerializer, only: :name
# has_one :location_names, serializer: LocationSerializer, only: :name
has_many :employees, serializer: EmployeeSerializer
has_many :primary_managers, serializer: ManagerSerializer
has_many :secondary_managers, serializer: ManagerSerializer
def employee_names
EmployeeSerializer.new(object.employees, only: :name) # + root: false if EmployeeSerializer uses a root
end
def location_names
LocationSerializer.new(object.locations, only: :name) # + root: false if LocationSerializer uses a root
end
end
And your controllers can call the DepartmentSerializer
like this:
class DepartmentController < ApplicationController # or other
def some_context_with_managers
render json: @department, except: %i(employees employee_names location_names)
end
# ... and so on
end