Module: Familia::ClassMethods

Defined in:
lib/familia/object.rb

Overview

Auto-extended into a class that includes Familia

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#parentObject

Returns the value of attribute parent.



132
133
134
# File 'lib/familia/object.rb', line 132

def parent
  @parent
end

Instance Method Details

#all(suffix = :object) ⇒ Object



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

def all(suffix=:object)
  # objects that could not be parsed will be nil
  keys(suffix).collect { |k| from_key(k) }.compact 
end

#any?(filter = '*') ⇒ Boolean

Returns:

  • (Boolean)


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

def any?(filter='*')
  size(filter) > 0
end

#class_redis_objectsObject



199
200
201
202
# File 'lib/familia/object.rb', line 199

def class_redis_objects
  @class_redis_objects ||= {}
  @class_redis_objects
end

#class_redis_objects?(name) ⇒ Boolean

Returns:

  • (Boolean)


203
204
205
# File 'lib/familia/object.rb', line 203

def class_redis_objects? name
  class_redis_objects.has_key? name.to_s.to_sym
end

#class_redis_objects_orderObject



195
196
197
198
# File 'lib/familia/object.rb', line 195

def class_redis_objects_order
  @class_redis_objects_order ||= []
  @class_redis_objects_order
end

#create(*args) ⇒ Object



217
218
219
220
221
222
# File 'lib/familia/object.rb', line 217

def create *args
  me = from_array *args
  raise "#{self} exists: #{me.rediskey}" if me.exists?
  me.save
  me
end

#db(v = nil) ⇒ Object



138
139
140
141
# File 'lib/familia/object.rb', line 138

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

#db=(db) ⇒ Object



142
# File 'lib/familia/object.rb', line 142

def db=(db) @db = db end

#destroy!(idx, suffix = :object) ⇒ Object



272
273
274
275
276
# File 'lib/familia/object.rb', line 272

def destroy! idx, suffix=:object
  ret = Familia.redis(self.uri).del rediskey(idx, suffix)
  Familia.trace :DELETED, Familia.redis(self.uri), "#{rediskey(idx, suffix)}: #{ret}", caller if Familia.debug?
  ret
end

#exists?(idx, suffix = :object) ⇒ Boolean

Returns:

  • (Boolean)


265
266
267
268
269
270
271
# File 'lib/familia/object.rb', line 265

def exists? idx, suffix=:object
  return false if idx.to_s.empty?
  objkey = rediskey idx, suffix
  ret = Familia.redis(self.uri).exists objkey
  Familia.trace :EXISTS, Familia.redis(self.uri), "#{rediskey(idx, suffix)} #{ret}", caller if Familia.debug?
  ret
end

#expand(short_idx, suffix = self.suffix) ⇒ Object



289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/familia/object.rb', line 289

def expand(short_idx, suffix=self.suffix)
  expand_key = Familia.rediskey(self.prefix, "#{short_idx}*", suffix)
  Familia.trace :EXPAND, Familia.redis(self.uri), expand_key, caller.first if Familia.debug?
  list = Familia.redis(self.uri).keys expand_key
  case list.size
  when 0
    nil
  when 1 
    matches = list.first.match(/\A#{Familia.rediskey(prefix)}\:(.+?)\:#{suffix}/) || []
    matches[1]
  else
    raise Familia::NonUniqueKey, "Short key returned more than 1 match" 
  end
end

#extended(obj) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/familia/object.rb', line 64

def extended(obj)
  obj.db = self.db
  obj.ttl = self.ttl
  obj.uri = self.uri
  obj.parent = self
  obj.class_zset :instances, :class => obj, :reference => true
  Familia.classes << obj
end

#find(suffix = '*') ⇒ Object



277
278
279
# File 'lib/familia/object.rb', line 277

def find suffix='*'
  list = Familia.redis(self.uri).keys(rediskey('*', suffix)) || []
end

#flushdbObject



160
161
162
163
# File 'lib/familia/object.rb', line 160

def flushdb
  Familia.info "flushing #{uri}"
  redis.flushdb
end

#from_index(idx) ⇒ Object

Note idx needs to be an appropriate index for the given class. If the index is multi-value it must be passed as an Array in the proper order. Does not call save.



247
248
249
250
251
# File 'lib/familia/object.rb', line 247

def from_index idx
  obj = new 
  obj.index = idx
  obj
end

#from_key(objkey) ⇒ Object

Raises:

  • (ArgumentError)


252
253
254
255
256
257
# File 'lib/familia/object.rb', line 252

def from_key objkey
  raise ArgumentError, "Empty key" if objkey.to_s.empty?    
  Familia.trace :LOAD, Familia.redis(self.uri), objkey, caller if Familia.debug?
  obj = Familia::String.new objkey, :class => self
  obj.value
end

#from_redis(idx, suffix = :object) ⇒ Object



258
259
260
261
262
263
264
# File 'lib/familia/object.rb', line 258

def from_redis idx, suffix=:object
  return nil if idx.to_s.empty?
  objkey = rediskey idx, suffix
  #Familia.trace :FROMREDIS, Familia.redis(self.uri), objkey, caller.first if Familia.debug?
  me = from_key objkey
  me
end

#from_redisdump(dump) ⇒ Object



129
130
131
# File 'lib/familia/object.rb', line 129

def from_redisdump dump
  dump # todo
end

#host(host = nil) ⇒ Object



143
# File 'lib/familia/object.rb', line 143

def host(host=nil) @host = host if host; @host end

#host=(host) ⇒ Object



144
# File 'lib/familia/object.rb', line 144

def host=(host) @host = host end

#index(i = nil, &blk) ⇒ Object

TODO: grab db, ttl, uri from parent def parent=(a) @parent = a end def parent(a=nil) @parent = a if a; @parent end



187
188
189
190
191
# File 'lib/familia/object.rb', line 187

def index(i=nil, &blk) 
  @index = i || blk if i || !blk.nil?
  @index ||= Familia.index
  @index
end

#inherited(obj) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/familia/object.rb', line 55

def inherited(obj)
  obj.db = self.db
  obj.uri = self.uri
  obj.ttl = self.ttl
  obj.parent = self
  obj.class_zset :instances, :class => obj, :reference => true
  Familia.classes << obj
  super(obj)
end

#install_class_redis_object(name, klass, opts) ⇒ Object

Creates a class method called name that returns an instance of the RedisObject klass

Raises:

  • (ArgumentError)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/familia/object.rb', line 103

def install_class_redis_object name, klass, opts
  raise ArgumentError, "Name is blank" if name.to_s.empty?
  name = name.to_s.to_sym
  opts = opts.nil? ? {} : opts.clone
  opts[:parent] = self unless opts.has_key?(:parent)
  # TODO: investigate using metaclass.redis_objects
  class_redis_objects_order << name
  class_redis_objects[name] = OpenStruct.new
  class_redis_objects[name].name = name
  class_redis_objects[name].klass = klass
  class_redis_objects[name].opts = opts 
  # An accessor method created in the metclass will
  # access the instance variables for this class. 
  metaclass.send :attr_reader, name
  metaclass.send :define_method, "#{name}=" do |v|
    send(name).replace v
  end
  metaclass.send :define_method, "#{name}?" do
    !send(name).empty?
  end
  redis_object = klass.new name, opts
  redis_object.freeze
  self.instance_variable_set("@#{name}", redis_object)
  class_redis_objects[name]
end

#install_redis_object(name, klass, opts) ⇒ Object

Creates an instance method called name that returns an instance of the RedisObject klass

Raises:

  • (ArgumentError)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/familia/object.rb', line 75

def install_redis_object name, klass, opts
  raise ArgumentError, "Name is blank" if name.to_s.empty?
  name = name.to_s.to_sym
  opts ||= {}
  redis_objects_order << name
  redis_objects[name] = OpenStruct.new
  redis_objects[name].name = name
  redis_objects[name].klass = klass
  redis_objects[name].opts = opts
  self.send :attr_reader, name
  define_method "#{name}=" do |v|
    self.send(name).replace v
  end
  define_method "#{name}?" do
    !self.send(name).empty?
  end
  redis_objects[name]
end

#keys(suffix = nil) ⇒ Object



164
165
166
# File 'lib/familia/object.rb', line 164

def keys(suffix=nil)
  self.redis.keys(rediskey('*',suffix)) || []
end

#load_or_create(idx) ⇒ Object

Returns an instance based on idx otherwise it creates and saves a new instance base on idx. See from_index



237
238
239
240
241
242
# File 'lib/familia/object.rb', line 237

def load_or_create idx
  return from_redis(idx) if exists?(idx)
  obj = from_index idx
  obj.save
  obj
end

#multiget(*ids) ⇒ Object



223
224
225
226
# File 'lib/familia/object.rb', line 223

def multiget(*ids)
  ids = rawmultiget(*ids)
  ids.compact.collect { |json| self.from_json(json) }.compact
end

#port(port = nil) ⇒ Object



145
# File 'lib/familia/object.rb', line 145

def port(port=nil) @port = port if port; @port end

#port=(port) ⇒ Object



146
# File 'lib/familia/object.rb', line 146

def port=(port) @port = port end

#prefix(a = nil) ⇒ Object



183
# File 'lib/familia/object.rb', line 183

def prefix(a=nil) @prefix = a if a; @prefix || self.name.downcase.gsub('::', Familia.delim).to_sym end

#prefix=(a) ⇒ Object



182
# File 'lib/familia/object.rb', line 182

def prefix=(a) @prefix = a end

#qstamp(quantum = nil, pattern = nil, now = Familia.now) ⇒ Object



94
95
96
97
98
99
# File 'lib/familia/object.rb', line 94

def qstamp quantum=nil, pattern=nil, now=Familia.now
  quantum ||= ttl || 10.minutes
  pattern ||= '%H%M'
  rounded = now - (now % quantum)
  Time.at(rounded).utc.strftime(pattern)
end

#rawmultiget(*ids) ⇒ Object



227
228
229
230
231
232
# File 'lib/familia/object.rb', line 227

def rawmultiget(*ids)
  ids.collect! { |objid| rediskey(objid) }
  return [] if ids.compact.empty?
  Familia.trace :MULTIGET, self.redis, "#{ids.size}: #{ids}", caller if Familia.debug?
  ids = self.redis.mget *ids
end

#redisObject



157
158
159
# File 'lib/familia/object.rb', line 157

def redis
  Familia.redis uri
end

#redis_object?(name) ⇒ Boolean

Returns:

  • (Boolean)


206
207
208
# File 'lib/familia/object.rb', line 206

def redis_object? name
  redis_objects.has_key? name.to_s.to_sym
end

#redis_objectsObject



213
214
215
216
# File 'lib/familia/object.rb', line 213

def redis_objects
  @redis_objects ||= {}
  @redis_objects
end

#redis_objects_orderObject



209
210
211
212
# File 'lib/familia/object.rb', line 209

def redis_objects_order
  @redis_objects_order ||= []
  @redis_objects_order
end

#rediskey(idx, suffix = self.suffix) ⇒ Object

idx can be a value or an Array of values used to create the index. We don’t enforce a default suffix; that’s left up to the instance. A nil suffix will not be included in the key.

Raises:

  • (RuntimeError)


283
284
285
286
287
288
# File 'lib/familia/object.rb', line 283

def rediskey idx, suffix=self.suffix
  raise RuntimeError, "No index for #{self}" if idx.to_s.empty?
  idx = Familia.join *idx if Array === idx
  idx &&= idx.to_s
  Familia.rediskey(prefix, idx, suffix)
end

#size(filter = '*') ⇒ Object



174
175
176
# File 'lib/familia/object.rb', line 174

def size(filter='*')
  self.redis.keys(rediskey(filter)).compact.size
end

#suffix(a = nil, &blk) ⇒ Object



177
178
179
180
181
# File 'lib/familia/object.rb', line 177

def suffix(a=nil, &blk) 
  @suffix = a || blk if a || !blk.nil?
  val = @suffix || Familia.default_suffix
  val
end

#suffixesObject



192
193
194
# File 'lib/familia/object.rb', line 192

def suffixes
  redis_objects.keys.uniq
end

#ttl(v = nil) ⇒ Object



133
134
135
136
# File 'lib/familia/object.rb', line 133

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

#ttl=(v) ⇒ Object



137
# File 'lib/familia/object.rb', line 137

def ttl=(v) @ttl = v end

#uri(uri = nil) ⇒ Object



151
152
153
154
155
156
# File 'lib/familia/object.rb', line 151

def uri(uri=nil) 
  self.uri = uri if !uri.to_s.empty?
  @uri ||= (parent ? parent.uri : Familia.uri)
  @uri.db = @db if @db && @uri.db.to_s != @db.to_s
  @uri
end

#uri=(uri) ⇒ Object



147
148
149
150
# File 'lib/familia/object.rb', line 147

def uri=(uri)
  uri = URI.parse uri if String === uri
  @uri = uri 
end