Module: Familia::RedisType::Serialization

Included in:
Familia::RedisType
Defined in:
lib/familia/redistype/serialization.rb

Instance Method Summary collapse

Instance Method Details

#from_redis(val) ⇒ Object?

Note:

If no class option is specified, the original value is returned unchanged.

Deserializes a single value from Redis.

NOTE: Currently only the RedisType class uses this method. Horreum fields are a newer addition and don’t support the full range of deserialization options that RedisType supports. It uses to_redis for serialization since everything becomes a string in Redis.

Parameters:

  • val (String, nil)

    The value to deserialize.

Returns:

  • (Object, nil)

    The deserialized object, the default value if val is nil, or nil if deserialization fails.



123
124
125
126
127
128
129
# File 'lib/familia/redistype/serialization.rb', line 123

def from_redis(val)
  return @opts[:default] if val.nil?
  return val unless @opts[:class]

  ret = multi_from_redis val
  ret&.first # return the object or nil
end

#multi_from_redis(*values) ⇒ Array<Object>

Deserializes multiple values from Redis, removing nil values.

Parameters:

  • values (Array<String>)

    The values to deserialize.

Returns:

  • (Array<Object>)

    Deserialized objects, with nil values removed.

See Also:



58
59
60
61
62
63
64
# File 'lib/familia/redistype/serialization.rb', line 58

def multi_from_redis(*values)
  # Avoid using compact! here. Using compact! as the last expression in the
  # method can unintentionally return nil if no changes are made, which is
  # not desirable. Instead, use compact to ensure the method returns the
  # expected value.
  multi_from_redis_with_nil(*values).compact
end

#multi_from_redis_with_nil(*values) ⇒ Array<Object, nil>

Note:

This method attempts to deserialize each value using the specified class’s load method. If deserialization fails for a value, it’s replaced with nil.

Deserializes multiple values from Redis, preserving nil values.

NOTE: ‘multi` in this method name refers to multiple values from redis and not the Redis server MULTI command.

Parameters:

  • values (Array<String>)

    The values to deserialize.

Returns:

  • (Array<Object, nil>)

    Deserialized objects, including nil values.

Raises:

  • (Familia::Problem)

    If the specified class doesn’t respond to the load method.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/familia/redistype/serialization.rb', line 81

def multi_from_redis_with_nil(*values)
  Familia.ld "multi_from_redis: (#{@opts}) #{values}"
  return [] if values.empty?
  return values.flatten unless @opts[:class]

  unless @opts[:class].respond_to?(load_method)
    raise Familia::Problem, "No such method: #{@opts[:class]}##{load_method}"
  end

  values.collect! do |obj|
    next if obj.nil?

    val = @opts[:class].send load_method, obj
    if val.nil?
      Familia.ld "[#{self.class}\#multi_from_redis] nil returned for #{@opts[:class]}\##{name}"
    end

    val
  rescue StandardError => e
    Familia.info val
    Familia.info "Parse error for #{rediskey} (#{load_method}): #{e.message}"
    Familia.info e.backtrace
    nil
  end

  values
end

#to_redis(val, strict_values: true) ⇒ String?

Note:

When a class option is specified, it uses that class’s serialization method. Otherwise, it relies on Familia.distinguisher for serialization.

Serializes a value for storage in Redis.

Examples:

With a class option

to_redis(User.new(name: "Cloe"), strict_values: false) #=> '{"name":"Cloe"}'

Without a class option

to_redis(123) #=> "123"
to_redis("hello") #=> "hello"

Parameters:

  • val (Object)

    The value to be serialized.

  • strict_values (Boolean) (defaults to: true)

    Whether to enforce strict value serialization (default: true).

Returns:

  • (String, nil)

    The serialized representation of the value, or nil if serialization fails.

Raises:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/familia/redistype/serialization.rb', line 29

def to_redis(val, strict_values: true)
  prepared = nil

  Familia.trace :TOREDIS, redis, "#{val}<#{val.class}|#{opts[:class]}>", caller(1..1) if Familia.debug?

  if opts[:class]
    prepared = Familia.distinguisher(opts[:class], strict_values: strict_values)
    Familia.ld "  from opts[class] <#{opts[:class]}>: #{prepared||'<nil>'}"
  end

  if prepared.nil?
    # Enforce strict values when no class option is specified
    prepared = Familia.distinguisher(val, strict_values: true)
    Familia.ld "  from <#{val.class}> => <#{prepared.class}>"
  end

  Familia.trace :TOREDIS, redis, "#{val}<#{val.class}|#{opts[:class]}> => #{prepared}<#{prepared.class}>", caller(1..1) if Familia.debug?

  Familia.warn "[#{self.class}\#to_redis] nil returned for #{opts[:class]}\##{name}" if prepared.nil?
  prepared
end