Class: Barley::Serializer

Inherits:
Object
  • Object
show all
Defined in:
lib/barley/serializer.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, cache: false, root: false) ⇒ Serializer

Returns a new instance of Serializer.

Examples:

with cache

Barley::Serializer.new(object, cache: true)

with cache and expires_in

Barley::Serializer.new(object, cache: {expires_in: 1.hour})

Parameters:

  • object (Object)

    the object to serialize

  • cache (Boolean, Hash<Symbol, ActiveSupport::Duration>) (defaults to: false)

    a boolean to cache the result, or a hash with options for the cache

  • root (Boolean) (defaults to: false)

    whether to include the root key in the hash



196
197
198
199
200
201
202
203
204
# File 'lib/barley/serializer.rb', line 196

def initialize(object, cache: false, root: false)
  @object = object
  @root = root
  @cache, @expires_in = if cache.is_a?(Hash)
    [true, cache[:expires_in]]
  else
    [cache, nil]
  end
end

Class Attribute Details

.defined_attributesObject

Returns the value of attribute defined_attributes.



9
10
11
# File 'lib/barley/serializer.rb', line 9

def defined_attributes
  @defined_attributes
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



6
7
8
# File 'lib/barley/serializer.rb', line 6

def context
  @context
end

#objectObject

Returns the value of attribute object.



5
6
7
# File 'lib/barley/serializer.rb', line 5

def object
  @object
end

Class Method Details

.attribute(key, key_name: nil, type: nil, &block) ⇒ Object

Defines a single attribute for the serializer

Type checking is done with Dry::Types. If a type is not provided, the value is returned as is. Dry::Types can be used to coerce the value to the desired type and to check constraints.

Examples:

simple attribute

attribute :id
# => {id: 1234}

attribute with a different key name

attribute :name, key_name: :full_name
# => {full_name: "John Doe"}

attribute with a type

attribute :email, type: Types::Strict::String
# => {email: "john.doe@example"}

attribute with a type and a block

attribute :email, type: Types::Strict::String do
  object.email.upcase
end
# => {email: "JOHN.DOE@EXAMPLE"}

Parameters:

  • key (Symbol)

    the attribute name

  • key_name (Symbol) (defaults to: nil)

    the key name in the hash

  • type (Dry::Types) (defaults to: nil)

    the type to use, or coerce the value to

  • block (Proc)

    a block to use to compute the value

Raises:

  • (Dry::Types::ConstraintError)

    if the type does not match

See Also:



76
77
78
79
80
81
82
83
84
# File 'lib/barley/serializer.rb', line 76

def attribute(key, key_name: nil, type: nil, &block)
  key_name ||= key
  define_method(key_name) do
    value = block ? instance_eval(&block) : object.send(key)
    type.nil? ? value : type[value]
  end

  self.defined_attributes = (defined_attributes || []) << key_name
end

.attributes(*keys) ⇒ Object

Defines attributes for the serializer

Accepts either a list of symbols or a hash of symbols and Dry::Types, or a mix of both

Examples:

only symbols

attributes :id, :name, :email
# => {id: 1234, name: "John Doe", email: "john.doe@example"}

with types

attributes id: Types::Strict::Integer, name: Types::Strict::String, email: Types::Strict::String
# => {id: 1234, name: "John Doe", email: "john.doe@example"}

with types and symbols

attributes :id, name: Types::Strict::String, email: Types::Strict::String
# => {id: 1234, name: "John Doe", email: "john.doe@example"}

Parameters:

  • keys (Hash<Symbol, Dry::Types>, Array<Symbol>)

    mix of symbols and hashes of symbols and Dry::Types

See Also:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/barley/serializer.rb', line 30

def attributes(*keys)
  if keys.last.is_a?(Hash)
    keys.pop.each do |key, type|
      attribute(key, type: type)
    end
  end
  keys.each do |key|
    if key.is_a?(Hash)
      attribute(key.keys.first, type: key.values.first)
    else
      attribute(key)
    end
  end
end

.many(key, key_name: nil, serializer: nil, cache: false, &block) ⇒ Object

Defines a collection association for the serializer

Examples:

using the default serializer of the associated model

many :groups
# => {groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

using a custom serializer

many :groups, serializer: MyCustomGroupSerializer
# => {groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

using a block with an inline serializer definition

many :groups do
  attributes :id, :name
end
# => {groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

using a different key name

many :groups, key_name: :my_groups
# => {my_groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

using cache

many :groups, cache: true
# => {groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

using cache and expires_in

many :groups, cache: {expires_in: 1.hour}
# => {groups: [{id: 1234, name: "Group 1"}, {id: 5678, name: "Group 2"}]}

Parameters:

  • key (Symbol)

    the association name

  • key_name (Symbol) (defaults to: nil)

    the key name in the hash

  • serializer (Class) (defaults to: nil)

    the serializer to use

  • cache (Boolean, Hash<Symbol, ActiveSupport::Duration>) (defaults to: false)

    whether to cache the result, or a hash with options for the cache

  • block (Proc)

    a block to use to define the serializer inline



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/barley/serializer.rb', line 169

def many(key, key_name: nil, serializer: nil, cache: false, &block)
  key_name ||= key
  if block
    serializer = Class.new(Barley::Serializer) do
      instance_eval(&block)
    end
  end
  define_method(key_name) do
    elements = object.send(key)
    return [] if elements.empty?

    el_serializer = serializer || elements.first.serializer.class
    elements.map { |element| el_serializer.new(element, cache: cache).serializable_hash }.reject(&:blank?)
  end
  self.defined_attributes = (defined_attributes || []) << key_name
end

.one(key, key_name: nil, serializer: nil, cache: false, &block) ⇒ Object

Defines a single association for the serializer

Examples:

using the default serializer of the associated model

one :group
# => {group: {id: 1234, name: "Group 1"}}

using a custom serializer

one :group, serializer: MyCustomGroupSerializer
# => {group: {id: 1234, name: "Group 1"}}

using a block with an inline serializer definition

one :group do
  attributes :id, :name
end
# => {group: {id: 1234, name: "Group 1"}}

using a different key name

one :group, key_name: :my_group
# => {my_group: {id: 1234, name: "Group 1"}}

using cache

one :group, cache: true
# => {group: {id: 1234, name: "Group 1"}}

using cache and expires_in

one :group, cache: {expires_in: 1.hour}
# => {group: {id: 1234, name: "Group 1"}}

Parameters:

  • key (Symbol)

    the association name

  • key_name (Symbol) (defaults to: nil)

    the key name in the hash

  • serializer (Class) (defaults to: nil)

    the serializer to use

  • cache (Boolean, Hash<Symbol, ActiveSupport::Duration>) (defaults to: false)

    whether to cache the result, or a hash with options for the cache

  • block (Proc)

    a block to use to define the serializer inline



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/barley/serializer.rb', line 119

def one(key, key_name: nil, serializer: nil, cache: false, &block)
  key_name ||= key
  if block
    serializer = Class.new(Barley::Serializer) do
      instance_eval(&block)
    end
  end
  define_method(key_name) do
    element = object.send(key)
    return {} if element.nil?

    el_serializer = serializer || element.serializer.class
    el_serializer.new(element, cache: cache).serializable_hash
  end
  self.defined_attributes = (defined_attributes || []) << key_name
end

Instance Method Details

#clear_cache(key: cache_base_key) ⇒ Boolean

Clears the cache for the object

Parameters:

  • key (String) (defaults to: cache_base_key)

    the cache key

Returns:

  • (Boolean)

    whether the cache was cleared



224
225
226
# File 'lib/barley/serializer.rb', line 224

def clear_cache(key: cache_base_key)
  Barley::Cache.delete(key)
end

#serializable_hashHash

Serializes the object

Returns:

  • (Hash)

    the serializable hash



209
210
211
212
213
214
215
216
217
# File 'lib/barley/serializer.rb', line 209

def serializable_hash
  if @cache
    Barley::Cache.fetch(cache_base_key, expires_in: @expires_in) do
      _serializable_hash
    end
  else
    _serializable_hash
  end
end

#with_context(**args) ⇒ Barley::Serializer

Sets the context object for the serializer

The context object is a Struct built from the given arguments. It can be used to pass additional data to the serializer. The context object is accessible in the serializer with the ‘context` attribute.

Examples:

serializer.with_context(current_user: current_user, locale: I18n.locale)
# => #<Barley::Serializer:0x00007f8f3b8b3e08 @object=#<Product id: 1, name: "Product 1">, @context=#<struct current_user=1, locale=:en>>
# In the serializer:
attribute :name do
  "#{object.name[context.locale]}" # Will use the locale from the context
end

Parameters:

  • args (Hash)

    the context object attributes

Returns:



241
242
243
244
245
# File 'lib/barley/serializer.rb', line 241

def with_context(**args)
  @context = Struct.new(*args.keys).new(*args.values)

  self
end