Class: Familia::RedisType

Inherits:
Object
  • Object
show all
Extended by:
Features
Includes:
Base, Commands, Serialization
Defined in:
lib/familia/redistype.rb,
lib/familia/redistype/commands.rb,
lib/familia/redistype/serialization.rb

Overview

rubocop:disable all

Direct Known Subclasses

HashKey, List, Set, SortedSet, String

Defined Under Namespace

Modules: Commands, Serialization

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from Features

#features_enabled

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Features

feature

Methods included from Serialization

#from_redis, #multi_from_redis, #multi_from_redis_with_nil, #to_redis

Methods included from Commands

#delete!, #echo, #exists?, #expire, #expireat, #move, #persist, #realttl, #rename, #renamenx, #type

Methods included from Base

add_feature, #generate_id, #update_expiration, #uuid

Constructor Details

#initialize(keystring, opts = {}) ⇒ RedisType

keystring: If parent is set, this will be used as the suffix for rediskey. Otherwise this becomes the value of the key. If this is an Array, the elements will be joined.

Options:

:class => A class that responds to Familia.load_method and Familia.dump_method. These will be used when loading and saving data from/to redis to unmarshal/marshal the class.

:parent => The Familia object that this redistype object belongs to. This can be a class that includes Familia or an instance.

:ttl => the time to live in seconds. When not nil, this will set the redis expire for this key whenever #save is called. You can also call it explicitly via #update_expiration.

:default => the default value (String-only)

:db => the redis database to use (ignored if :redis is used).

:redis => an instance of Redis.

:key => a hardcoded key to use instead of the deriving the from the name and parent (e.g. a derived key: customer:custid:secret_counter).

Uses the redis connection of the parent or the value of opts or Familia.redis (in that order).



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/familia/redistype.rb', line 94

def initialize(keystring, opts = {})
  #Familia.ld " [initializing] #{self.class} #{opts}"
  @keystring = keystring
  @keystring = @keystring.join(Familia.delim) if @keystring.is_a?(Array)

  # Remove all keys from the opts that are not in the allowed list
  @opts = opts || {}
  @opts = RedisType.valid_keys_only(@opts)

  # Apply the options to instance method setters of the same name
  @opts.each do |k, v|
    # Bewarde logging :parent instance here implicitly calls #to_s which for
    # some classes could include the identifier which could still be nil at
    # this point. This would result in a Familia::Problem being raised. So
    # to be on the safe-side here until we have a better understanding of
    # the issue, we'll just log the class name for each key-value pair.
    Familia.ld " [setting] #{k} #{v.class}"
    send(:"#{k}=", v) if respond_to? :"#{k}="
  end

  init if respond_to? :init
end

Class Attribute Details

.db(val = nil) ⇒ Object



39
40
41
42
# File 'lib/familia/redistype.rb', line 39

def db(val = nil)
  @db = val unless val.nil?
  @db || parent&.db
end

.parentObject

Returns the value of attribute parent.



27
28
29
# File 'lib/familia/redistype.rb', line 27

def parent
  @parent
end

.registered_typesObject (readonly)

Returns the value of attribute registered_types.



26
27
28
# File 'lib/familia/redistype.rb', line 26

def registered_types
  @registered_types
end

.uri(val = nil) ⇒ Object



44
45
46
47
# File 'lib/familia/redistype.rb', line 44

def uri(val = nil)
  @uri = val unless val.nil?
  @uri || (parent ? parent.uri : Familia.uri)
end

.valid_optionsObject (readonly)

Returns the value of attribute valid_options.



26
27
28
# File 'lib/familia/redistype.rb', line 26

def valid_options
  @valid_options
end

Instance Attribute Details

#dump_methodObject



201
202
203
# File 'lib/familia/redistype.rb', line 201

def dump_method
  @dump_method || self.class.dump_method
end

#keystringObject (readonly)

Returns the value of attribute keystring.



63
64
65
# File 'lib/familia/redistype.rb', line 63

def keystring
  @keystring
end

#load_methodObject



205
206
207
# File 'lib/familia/redistype.rb', line 205

def load_method
  @load_method || self.class.load_method
end

#optsObject (readonly)

Returns the value of attribute opts.



63
64
65
# File 'lib/familia/redistype.rb', line 63

def opts
  @opts
end

#parentObject (readonly)

Returns the value of attribute parent.



63
64
65
# File 'lib/familia/redistype.rb', line 63

def parent
  @parent
end

Class Method Details

.inherited(obj) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/familia/redistype.rb', line 49

def inherited(obj)
  Familia.trace :REDISTYPE, nil, "#{obj} is my kinda type", caller(1..1) if Familia.debug?
  obj.db = db
  obj.ttl = ttl # method added via Features::Expiration
  obj.uri = uri
  obj.parent = self
  super(obj)
end

.register(klass, methname) ⇒ Object

To be called inside every class that inherits RedisType methname is the term used for the class and instance methods that are created for the given klass (e.g. set, list, etc)



33
34
35
36
37
# File 'lib/familia/redistype.rb', line 33

def register(klass, methname)
  Familia.ld "[#{self}] Registering #{klass} as #{methname.inspect}"

  @registered_types[methname] = klass
end

.valid_keys_only(opts) ⇒ Object



58
59
60
# File 'lib/familia/redistype.rb', line 58

def valid_keys_only(opts)
  opts.select { |k, _| RedisType.valid_options.include? k }
end

Instance Method Details

#class?Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/familia/redistype.rb', line 173

def class?
  !@opts[:class].to_s.empty? && @opts[:class].is_a?(Familia)
end

#dbObject



193
194
195
# File 'lib/familia/redistype.rb', line 193

def db
  @opts[:db] || self.class.db
end

#parent?Boolean

Returns:

  • (Boolean)


185
186
187
# File 'lib/familia/redistype.rb', line 185

def parent?
  parent_class? || parent_instance?
end

#parent_class?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/familia/redistype.rb', line 181

def parent_class?
  parent.is_a?(Class) && parent <= Familia::Horreum
end

#parent_instance?Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/familia/redistype.rb', line 177

def parent_instance?
  parent.is_a?(Familia::Horreum)
end

#redisObject



117
118
119
120
121
# File 'lib/familia/redistype.rb', line 117

def redis
  return @redis if @redis

  parent? ? parent.redis : Familia.redis(opts[:db])
end

#rediskeyString

Produces the full Redis key for this object.

This method determines the appropriate Redis key based on the context of the RedisType object:

  1. If a hardcoded key is set in the options, it returns that key.

  2. For instance-level RedisType objects, it uses the parent instance’s rediskey method.

  3. For class-level RedisType objects, it uses the parent class’s rediskey method.

  4. For standalone RedisType objects, it uses the keystring as the full Redis key.

For class-level RedisType objects (parent_class? == true):

  • The suffix is optional and used to differentiate between different types of objects.

  • If no suffix is provided, the class’s default suffix is used (via the self.suffix method).

  • If a nil suffix is explicitly passed, it won’t appear in the resulting Redis key.

  • Passing nil as the suffix is how class-level RedisType objects are created without the global default ‘object’ suffix.

Examples:

Instance-level RedisType

user_instance.some_redistype.rediskey  # => "user:123:some_redistype"

Class-level RedisType

User.some_redistype.rediskey  # => "user:some_redistype"

Standalone RedisType

RedisType.new("mykey").rediskey  # => "mykey"

Class-level RedisType with explicit nil suffix

User.rediskey("123", nil)  # => "user:123"

Returns:

  • (String)

    The full Redis key.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/familia/redistype.rb', line 153

def rediskey
  # Return the hardcoded key if it's set. This is useful for
  # support legacy keys that aren't derived in the same way.
  return opts[:key] if opts[:key]

  if parent_instance?
    # This is an instance-level redistype object so the parent instance's
    # rediskey method is defined in Familia::Horreum::InstanceMethods.
    parent.rediskey(keystring)
  elsif parent_class?
    # This is a class-level redistype object so the parent class' rediskey
    # method is defined in Familia::Horreum::ClassMethods.
    parent.rediskey(keystring, nil)
  else
    # This is a standalone RedisType object where it's keystring
    # is the full redis key.
    keystring
  end
end

#uriObject



197
198
199
# File 'lib/familia/redistype.rb', line 197

def uri
  @opts[:uri] || self.class.uri
end