Class: Familia::RedisObject

Inherits:
Object
  • Object
show all
Defined in:
lib/familia/redisobject.rb

Direct Known Subclasses

HashKey, List, Set, SortedSet, String

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, opts = {}) ⇒ RedisObject

name: 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.

:reference => When true the index of the given value will be stored rather than the marshaled value. This assumes that the marshaled object is stored at a separate key. When read, from_redis looks for that separate key and returns the unmarshaled object. :class must be specified. Default: false.

:extend => Extend this instance with the functionality in an other module. Literally: “self.extend opts”.

:parent => The Familia object that this redis 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.

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



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/familia/redisobject.rb', line 86

def initialize name, opts={}
  @name, @opts = name, opts
  @name = @name.join(Familia.delim) if Array === @name
  #Familia.ld [name, opts, caller[0]].inspect
  self.extend @opts[:extend] if Module === @opts[:extend]
  @db = @opts.delete(:db)
  @ttl = @opts.delete(:ttl) 
  @parent = @opts.delete(:parent)
  @redis ||= @opts.delete(:redis)
  init if respond_to? :init
end

Class Attribute Details

.classesObject



19
20
21
# File 'lib/familia/redisobject.rb', line 19

def RedisObject.classes
  @classes
end

.db(v = nil) ⇒ Object



31
32
33
34
# File 'lib/familia/redisobject.rb', line 31

def db v=nil
  @db = v unless v.nil?
  @db || (parent ? parent.db : nil)
end

.parentObject

Returns the value of attribute parent.



25
26
27
# File 'lib/familia/redisobject.rb', line 25

def parent
  @parent
end

.ttl(v = nil) ⇒ Object



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

def ttl v=nil
  @ttl = v unless v.nil?
  @ttl || (parent ? parent.ttl : nil)
end

.uri(v = nil) ⇒ Object



35
36
37
38
# File 'lib/familia/redisobject.rb', line 35

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

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



49
50
51
# File 'lib/familia/redisobject.rb', line 49

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



49
50
51
# File 'lib/familia/redisobject.rb', line 49

def parent
  @parent
end

#redisObject



98
99
100
101
# File 'lib/familia/redisobject.rb', line 98

def redis
  return @redis if @redis
  parent? ? parent.redis : Familia.redis(db)
end

Class Method Details

.inherited(obj) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/familia/redisobject.rb', line 39

def inherited(obj)
  obj.db = self.db
  obj.ttl = self.ttl
  obj.uri = self.uri
  obj.parent = self
  RedisObject.classes << obj
  super(obj)
end

.register(klass, meth) ⇒ Object

To be called inside every class that inherits RedisObject meth becomes the base for the class and instances methods that are created for the given klass (e.g. Obj.list)



11
12
13
# File 'lib/familia/redisobject.rb', line 11

def RedisObject.register klass, meth
  registration[meth] = klass
end

.registrationObject



15
16
17
# File 'lib/familia/redisobject.rb', line 15

def RedisObject.registration
  @registration
end

Instance Method Details

#dbObject

Returns the most likely value for db, checking (in this order):

* the value from :class if it's a Familia object
* the value from :parent
* the value self.class.db
* assumes the db is 0

After this is called once, this method will always return the same value.



115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/familia/redisobject.rb', line 115

def db 
  return @db if @db
  # Note it's important that we select this value at the last
  # possible moment rather than in initialize b/c the value 
  # could be modified after that but before this is called. 
  if @opts[:class] && @opts[:class].ancestors.member?(Familia)
    @db = @opts[:class].db 
  else
    @db = parent? ? parent.db : self.class.db
  end
  @db ||= 0
  @db
end

#deleteObject Also known as: clear, del



156
157
158
# File 'lib/familia/redisobject.rb', line 156

def delete 
  redis.del rediskey
end

#dump_methodObject



183
184
185
# File 'lib/familia/redisobject.rb', line 183

def dump_method
  @opts[:dump_method] || Familia.dump_method
end

#exists?Boolean

def destroy!

clear
# TODO: delete redis objects for this instance

end

Returns:

  • (Boolean)


167
168
169
# File 'lib/familia/redisobject.rb', line 167

def exists?
  redis.exists(rediskey) && !size.zero?
end

#expire(sec) ⇒ Object



175
176
177
# File 'lib/familia/redisobject.rb', line 175

def expire sec
  redis.expire rediskey, sec.to_i
end

#expireat(unixtime) ⇒ Object



179
180
181
# File 'lib/familia/redisobject.rb', line 179

def expireat unixtime
  redis.expireat rediskey, unixtime
end

#from_redis(v) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/familia/redisobject.rb', line 213

def from_redis v
  return @opts[:default] if v.nil?
  return v unless @opts[:class]
  case @opts[:class]
  when String
    v.to_s
  when Fixnum, Float
    @opts[:class].induced_from v
  else
    if @opts[:reference] == true
      @opts[:class].from_redis v
    else
      if @opts[:class].respond_to? load_method
        @opts[:class].send load_method, v
      else
        raise Familia::Problem, "No such method: #{@opts[:class]}##{load_method}"
      end
    end
  end
rescue => ex
  Familia.info v
  Familia.info "Parse error for #{rediskey} (#{load_method}): #{ex.message}"
  Familia.info ex.backtrace
  nil
end

#load_methodObject



187
188
189
# File 'lib/familia/redisobject.rb', line 187

def load_method
  @opts[:load_method] || Familia.load_method
end

#move(db) ⇒ Object



146
147
148
# File 'lib/familia/redisobject.rb', line 146

def move db
  redis.move rediskey, db
end

#parent?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/familia/redisobject.rb', line 135

def parent?
  Class === parent || Module === parent || parent.kind_of?(Familia)
end

#realttlObject



171
172
173
# File 'lib/familia/redisobject.rb', line 171

def realttl
  redis.ttl rediskey
end

#rediskeyObject

returns a redis key based on the parent object so it will include the proper index.



131
132
133
# File 'lib/familia/redisobject.rb', line 131

def rediskey
  parent? ? parent.rediskey(name) : [name].flatten.compact.join(Familia.delim)
end

#to_redis(v) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/familia/redisobject.rb', line 191

def to_redis v
  return v unless @opts[:class]
  case @opts[:class]
  when String, Fixnum, Float, Gibbler::Digest
    v
  else
    if @opts[:reference] == true
      unless v.respond_to? :index
        raise Familia::Problem, "#{v.class} does not have an index method"
      end
      unless v.kind_of?(Familia)
        raise Familia::Problem, "#{v.class} is not Familia (#{name})"
      end
      v.index
    elsif v.respond_to? dump_method
      v.send dump_method
    else
      raise Familia::Problem, "No such method: #{v.class}.#{dump_method}"
    end
  end
end

#ttlObject



103
104
105
# File 'lib/familia/redisobject.rb', line 103

def ttl
  @ttl || self.class.ttl
end

#typeObject

TODO: rename, renamenx



152
153
154
# File 'lib/familia/redisobject.rb', line 152

def type 
  redis.type rediskey
end

#update_expiration(ttl = nil) ⇒ Object



139
140
141
142
143
144
# File 'lib/familia/redisobject.rb', line 139

def update_expiration(ttl=nil)
  ttl ||= @opts[:ttl] || self.class.ttl
  return unless ttl && ttl.to_i > 0
  Familia.ld "#{rediskey} to #{ttl}"
  expire ttl.to_i
end