Factor out ancestor class Field of Attribute and Reflection.

This commit is contained in:
Lucas Hosseini 2016-01-04 20:40:56 +01:00
parent 6860318133
commit 40ed7b57bd
3 changed files with 87 additions and 74 deletions

View File

@ -1,40 +1,25 @@
require 'active_model/serializer/field'
module ActiveModel module ActiveModel
class Serializer class Serializer
Attribute = Struct.new(:name, :options, :block) do # Holds all the meta-data about an attribute as it was specified in the
def value(serializer) # ActiveModel::Serializer class.
if block #
serializer.instance_eval(&block) # @example
else # class PostSerializer < ActiveModel::Serializer
serializer.read_attribute_for_serialization(name) # attribute :content
end # attribute :name, key: :title
end # attribute :email, key: :author_email, if: :user_logged_in?
# attribute :preview do
def included?(serializer) # truncate(object.content)
case condition # end
when :if #
serializer.public_send(condition) # def user_logged_in?
when :unless # current_user.logged_in?
!serializer.public_send(condition) # end
else # end
true #
end class Attribute < Field
end
private
def condition_type
if options.key?(:if)
:if
elsif options.key?(:unless)
:unless
else
:none
end
end
def condition
options[condition_type]
end
end end
end end
end end

View File

@ -0,0 +1,55 @@
module ActiveModel
class Serializer
# Holds all the meta-data about a field (i.e. attribute or association) as it was
# specified in the ActiveModel::Serializer class.
# Notice that the field block is evaluated in the context of the serializer.
Field = Struct.new(:name, :options, :block) do
# Compute the actual value of a field for a given serializer instance.
# @param [Serializer] The serializer instance for which the value is computed.
# @return [Object] value
#
# @api private
#
def value(serializer)
if block
serializer.instance_eval(&block)
else
serializer.read_attribute_for_serialization(name)
end
end
# Decide whether the field should be serialized by the given serializer instance.
# @param [Serializer] The serializer instance
# @return [Bool]
#
# @api private
#
def included?(serializer)
case condition
when :if
serializer.public_send(condition)
when :unless
!serializer.public_send(condition)
else
true
end
end
private
def condition_type
if options.key?(:if)
:if
elsif options.key?(:unless)
:unless
else
:none
end
end
def condition
options[condition_type]
end
end
end
end

View File

@ -1,18 +1,24 @@
require 'active_model/serializer/field'
module ActiveModel module ActiveModel
class Serializer class Serializer
# Holds all the meta-data about an association as it was specified in the # Holds all the meta-data about an association as it was specified in the
# ActiveModel::Serializer class. # ActiveModel::Serializer class.
# #
# @example # @example
# class PostSerializer < ActiveModel::Serializer # class PostSerializer < ActiveModel::Serializer
# has_one :author, serializer: AuthorSerializer # has_one :author, serializer: AuthorSerializer
# has_many :comments # has_many :comments
# has_many :comments, key: :last_comments do # has_many :comments, key: :last_comments do
# object.comments.last(1) # object.comments.last(1)
# end # end
# end # has_many :secret_meta_data, if: :is_admin?
#
# def is_admin?
# current_user.admin?
# end
# end
# #
# Notice that the association block is evaluated in the context of the serializer.
# Specifically, the association 'comments' is evaluated two different ways: # Specifically, the association 'comments' is evaluated two different ways:
# 1) as 'comments' and named 'comments'. # 1) as 'comments' and named 'comments'.
# 2) as 'object.comments.last(1)' and named 'last_comments'. # 2) as 'object.comments.last(1)' and named 'last_comments'.
@ -21,32 +27,13 @@ module ActiveModel
# # [ # # [
# # HasOneReflection.new(:author, serializer: AuthorSerializer), # # HasOneReflection.new(:author, serializer: AuthorSerializer),
# # HasManyReflection.new(:comments) # # HasManyReflection.new(:comments)
# # HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
# # HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
# # ] # # ]
# #
# So you can inspect reflections in your Adapters. # So you can inspect reflections in your Adapters.
# #
Reflection = Struct.new(:name, :options, :block) do class Reflection < Field
# @api private
def value(instance)
if block
instance.instance_eval(&block)
else
instance.read_attribute_for_serialization(name)
end
end
# @api private
def included?(serializer)
case condition_type
when :if
serializer.public_send(condition)
when :unless
!serializer.public_send(condition)
else
true
end
end
# Build association. This method is used internally to # Build association. This method is used internally to
# build serializer's association by its reflection. # build serializer's association by its reflection.
# #
@ -91,20 +78,6 @@ module ActiveModel
private private
def condition_type
if options.key?(:if)
:if
elsif options.key?(:unless)
:unless
else
:none
end
end
def condition
options[condition_type]
end
def serializer_options(subject, parent_serializer_options, reflection_options) def serializer_options(subject, parent_serializer_options, reflection_options)
serializer = reflection_options.fetch(:serializer, nil) serializer = reflection_options.fetch(:serializer, nil)