Class: Moneta::Transform::Serializer Abstract

Inherits:
Moneta::Transform show all
Defined in:
lib/moneta/transform/serializer.rb

Overview

This class is abstract.

Subclasses should implement #serialize and optionally #deserialize; or use Serializer.delegate_to. They may also implement #encoded? if it is possible to efficiently test whether something was encoded (e.g. using a magic number).

A Serializer is a special type of Transform intended for serializing objects to text. Moneta has historically distinguished serializers from other transforms by only transforming non-string values, which is still be default behaviour of this class, though it can be disabled (i.e. to apply serialization to everything) by initializing with serialize_unless_string set to false.

Because of the above behaviour, serializers are by default not decodable, because it is pretty much impossible to tell for some given string whether it was originally a string, or if it was encoded. Setting serialize_unless_string will enable decoding.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Moneta::Transform

#method_missing, #respond_to_missing?

Constructor Details

#initialize(serialize_unless_string: false, **_) ⇒ Serializer

Serializers implement #encode and #decode based on the subclass’ implementation of #serialize and #deserialize, and using the serialize_unless_string option. If it’s enabled, then #encode will only call #serialize if the input is not a string.

Parameters:

  • serialize_unless_string (Boolean) (defaults to: false)

    Whether to skip serialization of strings



79
80
81
82
# File 'lib/moneta/transform/serializer.rb', line 79

def initialize(serialize_unless_string: false, **_)
  super
  @serialize_unless_string = serialize_unless_string
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Moneta::Transform

Class Method Details

.delegate_to(object, methods = nil) ⇒ Object

This helper can be used in subclasses to implement #serialize and #deserialize, similar to Moneta::Transform.delegate_to. #deserialize is optional - if not delegated or implemented, the transform will be unserializable.

Examples:

Delegate to stdlib JSON library

require 'json'

# By inheriting from Serializer, this class will by default only serialize to JSON when the input is not a
# string
class MyJsonSerializer < Moneta::Transform::Serializer
  delegate_to ::JSON
  # equvalent to
  delegate_to ::JSON, %[dump load]
end

serializer1 = MyJsonSerializer.new
serializer2 = MyJsonSerializer.new(serialize_unless_string: false)

serializer1.encode('test')    #=> 'test'
serializer1.encode(%w[1 2 3]) #=> '["1","2","3"]'
serializer1.decode('test')    #=> NotImplementedError
serializer2.encode('test')    #=> '"test"'
serializer2.decode('"test"')  #=> 'test'

Parameters:

  • object (Module)

    The object to delegate to

  • methods (<Symbol,Symbol>) (defaults to: nil)

    The methods on object to delegate to



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/moneta/transform/serializer.rb', line 53

def self.delegate_to(object, methods = nil)
  extend Forwardable

  serialize, deserialize =
    if methods && methods.length >= 1
      methods
    elsif object.respond_to?(:encode)
      i[encode decode]
    elsif object.respond_to?(:dump)
      i[dump load]
    else
      raise "Could not determine what methods to use on #{object}"
    end

  def_delegator object, serialize, :serialize

  if deserialize && object.respond_to?(deserialize)
    def_delegator object, deserialize, :deserialize
  end
end

Instance Method Details

#decodable?Boolean

Returns true iff the class has implemented #deserialize and is not running in serialize_unless_string mode.

Returns:

  • (Boolean)


110
111
112
# File 'lib/moneta/transform/serializer.rb', line 110

def decodable?
  !@serialize_unless_string && respond_to?(:deserialize)
end

#decode(value) ⇒ Object

This method is abstract.

Subclasses where it is possible to deserialize again should implement this method

This method will be called by #decode except when in serialize_unless_string mode (in which case deserialization is disabled).

Parameters:

  • value (Object)

    the thing to decode

Returns:

  • (Object)


102
103
104
105
# File 'lib/moneta/transform/serializer.rb', line 102

def decode(value)
  raise NotImplementedError, "cannot decode in serialize_unless_string mode" if @serialize_unless_string
  deserialize(value)
end

#encode(value) ⇒ Object

Calls #serialize provided that either the serialize_unless_string option was disabled, or the input is not a string.

Parameters:

  • value (Object)

    object to encode

Returns:

  • (Object)

    The serialized object (usually string)



89
90
91
92
93
94
95
# File 'lib/moneta/transform/serializer.rb', line 89

def encode(value)
  if @serialize_unless_string && String === value
    value
  else
    serialize(value)
  end
end

#serialize(value) ⇒ Object

This method is abstract.

All Subclasses should implement this method

This method will be called by #encode except when the value being encoded is a string, and the object is in serialize_unless_string mode.

Parameters:

  • value (Object)

    the thing to encode

Returns:

  • (Object)


# File 'lib/moneta/transform/serializer.rb', line 114