class Cuprum::Rails::Serializers::Json::AttributesSerializer
Converts the object to JSON by serializing the specified attributes.
When called, the serializer will convert each of the given attributes to JSON using the given serializers.
Defined attributes are inherited from the parent serializer. This allows you to extend existing serializers with additional functionality.
@example Defining A Base Serializer
class RecordSerializer < Cuprum::Rails::Serializers::Json::AttributesSerializer # rubocop:disable Layout/LineLength attribute :id end book = Book.new( id: 10, title: 'Gideon the Ninth', author: 'Tamsyn Muir', published_at: '2019-09-10' ) serializers = Cuprum::Rails::Serializers::Json.default_serializers RecordSerializer.new.call(book, serializers: serializers) #=> { id: 10 }
@example Defining A Record Serializer
class BookSerializer < RecordSerializer attribute :title, Cuprum::Rails::Serializers::Json::IdentitySerializer.instance # rubocop:disable Layout/LineLength attribute :author do |author| "by: #{author}" end end BookSerializer.new.call(book, serializers: serializers) #=> { id: 10, title: 'Gideon the Ninth', author: 'by: Tamsyn Muir' }
@example Defining a Serializer
Subclass
class PublishedBookSerializer < BookSerializer attribute :published_at end PublishedBookSerializer.new.call(book, serializers: serializers) #=> { id: 10, title: 'Gideon the Ninth', author: 'by: Tamsyn Muir', published_at: '2019-09-10' }
Public Class Methods
Registers the attribute to be serialized.
This class method will raise an AbstractSerializerError
if called on AttributesSerializer
directly. Instead, create a subclass and define attributes on that subclass.
@return [Class] the serializer class.
@raise [AbstractSerializerError] if called on AttributesSerializer
.
@see AttributesSerializer#call
.
@overload attribute(attr_name)
Registers the attribute for serialization. When the serializer is called, the value of the attribute will be converted to JSON using the serializers passed to #call. @param attr_name [String, Symbol] The name of the attribute to serialize.
@overload attribute(attr_name, serializer)
Registers the attribute for serialization. When the serializer is called, the given serializer will be called with the value of the attribute and the configured serializers. @param attr_name [String, Symbol] The name of the attribute to serialize. @param serializer [Cuprum::Rails::Serializers::Json::Serializer] the serializer to use when converting the attribute to JSON.
@overload attribute(attr_name, &block)
Registers the attribute for serialization. When the serializer is called, the block will be called with the value of the attribute and the configured serializers. @param attr_name [String, Symbol] The name of the attribute to serialize. @yield The value of the attribute and the configured serializers. @yieldreturn the attribute value converted to JSON.
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 104 def attribute(attr_name, serializer = nil, &block) validate_subclass! validate_attribute_name!(attr_name) validate_serializer!(serializer) own_attributes[attr_name.to_s] = serializer || block self end
@return [Hash<String, Object>] the defined attributes and respective
serializers.
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 116 def attributes(*_, **_) all_attributes end
Protected Class Methods
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 122 def own_attributes @own_attributes ||= {} end
Private Class Methods
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 128 def all_attributes ancestors .select do |ancestor| ancestor < Cuprum::Rails::Serializers::Json::AttributesSerializer end # rubocop:disable Style/MultilineBlockChain .reverse_each .reduce({}) { |hsh, ancestor| hsh.merge(ancestor.own_attributes) } end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 137 def validate_attribute_name!(attr_name) raise ArgumentError, "attribute name can't be blank" if attr_name.nil? unless attr_name.is_a?(String) || attr_name.is_a?(Symbol) raise ArgumentError, 'attribute name must be a string or symbol' end return unless attr_name.empty? raise ArgumentError, "attribute name can't be blank" end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 149 def validate_serializer!(serializer) return if serializer.nil? || serializer.respond_to?(:call) raise ArgumentError, 'serializer must respond to #call' end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 155 def validate_subclass! unless self == Cuprum::Rails::Serializers::Json::AttributesSerializer return end raise AbstractSerializerError, 'AttributesSerializer is an abstract class - create a subclass to' \ ' define attributes' end
Public Instance Methods
Converts the defined attributes to JSON.
@param object [Object] The object to convert to JSON. @param serializers [Hash<Class, call
>] The serializers for different
object types.
@return [Hash<String, Object] a JSON-compatible representation of the
object's attributes.
Cuprum::Rails::Serializers::Json::Serializer#call
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 174 def call(object, serializers:) self.class.attributes.each.with_object({}) \ do |(attr_name, serializer), hsh| attr_value = object.send(attr_name) hsh[attr_name] = serialize_attribute( attr_value: attr_value, serializer: serializer, serializers: serializers ) { super(attr_value, serializers: serializers) } end end
Private Instance Methods
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 189 def apply_block(attr_value, block:, serializers:) args = block_argument?(block) ? [attr_value] : [] kwargs = block_keyword?(block) ? { serializers: serializers } : {} kwargs.empty? ? block.call(*args) : block.call(*args, **kwargs) end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 196 def block_argument?(block) block.parameters.any? { |type, _| type == :req || type == :rest } # rubocop:disable Style/MultipleComparison end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 200 def block_keyword?(block) block.parameters.any? do |type, name| (type == :keyreq && name == :serializers) || type == :keyrest end end
# File lib/cuprum/rails/serializers/json/attributes_serializer.rb, line 206 def serialize_attribute(attr_value:, serializer:, serializers:) case serializer when Cuprum::Rails::Serializers::Json::Serializer serializer.call(attr_value) when Proc apply_block(attr_value, block: serializer, serializers: serializers) else yield end end