Usage
Basic attributes
Use attributes when fields should always be included.
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :id, :first_name, :last_name, :email
end
UserSerializer.new(user).to_h
Optional single attributes
Use attribute for a single field that should be opt-in unless you set always_include: true.
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :id, :first_name
attribute :email
end
UserSerializer.new(user).to_h
# => { id: 1, first_name: "Ada" }
UserSerializer.new(user, includes: [:email]).to_h
# => { id: 1, first_name: "Ada", email: "ada@example.com" }
This also works with a proc shorthand:
class UserSerializer < Mutils::Serialization::BaseSerializer
attribute :object_id, &:id
end
Computed methods
Use custom_methods for computed fields that should always be included.
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :first_name, :last_name
custom_methods :full_name
def full_name
"#{scope.first_name} #{scope.last_name}"
end
end
Use custom_method for an opt-in computed field:
class HouseSerializer < Mutils::Serialization::BaseSerializer
custom_method :house_tag
def house_tag
"#{scope.name}--#{scope.number}"
end
end
HouseSerializer.new(house, includes: [:house_tag]).to_h
Block attributes
Use a block when the serialized value is easiest to express inline.
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :first_name, :last_name
attribute :full_name do |user|
"#{user.first_name} #{user.last_name}"
end
end
If you pass params:, the block can receive them as the second argument:
class UserSerializer < Mutils::Serialization::BaseSerializer
attribute :is_owner do |user, params|
params[:owner].id == user.id
end
end
UserSerializer.new(user, params: { owner: current_user }).to_h
Conditional inclusion
Both attributes and relationships accept if: proc.
The proc can take:
|scope||scope, params|
Example:
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :id, :first_name
attribute :email, if: proc { |scope, params| params[:show_email] == true }
end
UserSerializer.new(user).to_h
UserSerializer.new(user, params: { show_email: true }).to_h
Relationships
Mutils supports belongs_to, has_one, and has_many.
Every relationship must declare a serializer:
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :id, :first_name
belongs_to :company, serializer: CompanySerializer, always_include: true
has_one :account, serializer: AccountSerializer
has_many :comments, serializer: CommentSerializer
end
Relationship inclusion rules:
- relationships are opt-in by default
- set
always_include: trueto include them every time - use
includes:to request optional relationships
UserSerializer.new(user, includes: [:account, :comments]).to_h
Relationship labels
Use label: to rename the serialized key:
class UserSerializer < Mutils::Serialization::BaseSerializer
belongs_to :company, serializer: CompanySerializer, label: "organization"
end
The output key becomes :organization.
For collections, Mutils pluralizes the label automatically.
Root naming
Use name_tag to control the root key used by as_json and to_json.
class UserSerializer < Mutils::Serialization::BaseSerializer
name_tag "person", true
attributes :id, :first_name
end
UserSerializer.new(user).as_json
# => { "person" => { ... } }
Common forms:
name_tag "person", trueinclude a root key on the top-level serializername_tag "person", falseset the serializer name but do not wrap the top-level outputname_tag "person"same asfalse- no
name_taguse the serialized object’s class name
For collections with a root key, Mutils pluralizes the configured name.
Output methods
Use the output method that matches your call site:
to_hreturns a Ruby hash or arrayas_jsonreturns a hash, optionally wrapped with a root key at the top levelto_jsonreturns a JSON string
Examples:
UserSerializer.new(user).to_h
UserSerializer.new(user).as_json
UserSerializer.new(user).to_json
UserSerializer.new(users).to_h
Complete example
class CountrySerializer < Mutils::Serialization::BaseSerializer
attributes :name
end
class HouseSerializer < Mutils::Serialization::BaseSerializer
custom_methods :house_tag
def house_tag
"#{scope.name}--#{scope.number}"
end
end
class UserSerializer < Mutils::Serialization::BaseSerializer
attributes :first_name, :last_name
custom_methods :full_name
has_many :houses, serializer: HouseSerializer, always_include: true
belongs_to :country, serializer: CountrySerializer, always_include: true
attribute :object_id, &:id
def full_name
"#{scope.first_name} #{scope.last_name}"
end
end
UserSerializer.new(user).to_h
UserSerializer.new(user, includes: [:object_id]).to_json
Notes
includes:matches the declared field name, not the renamedlabel:- nested relationship serializers run independently with their own serializer declarations
- passing a collection to the serializer returns an array from
to_h