module Familia::InstanceMethods

Public Class Methods

new(*args) click to toggle source

A default initialize method. This will be replaced if a class defines its own initialize method after including Familia. In that case, the replacement must call initialize_redis_objects.

# File lib/familia/object.rb, line 312
def initialize *args
  initialize_redis_objects
  init *args if respond_to? :init
end

Public Instance Methods

allkeys() click to toggle source

def rediskeys

self.class.redis_objects.each do |redis_object_definition|

end

end

# File lib/familia/object.rb, line 370
def allkeys
  # TODO: Use redis_objects instead
  keynames = []
  self.class.suffixes.each do |sfx| 
    keynames << rediskey(sfx)
  end
  keynames
end
destroy!() click to toggle source
# File lib/familia/object.rb, line 427
def destroy!
  ret = object_proxy.delete
  if Familia.debug?
    Familia.trace :DELETED, Familia.redis(self.class.uri), "#{rediskey}: #{ret}", caller.first if Familia.debug?
  end
  self.class.instances.rem self if ret > 0
  ret
end
exists?() click to toggle source
# File lib/familia/object.rb, line 360
def exists?
  Familia.redis(self.class.uri).exists rediskey
end
expire(ttl=nil) click to toggle source
# File lib/familia/object.rb, line 492
def expire(ttl=nil)
  ttl ||= self.class.ttl
  Familia.redis(self.class.uri).expire rediskey, ttl.to_i
end
from_redis() click to toggle source
# File lib/familia/object.rb, line 343
def from_redis 
  self.class.from_redis self.index
end
index() click to toggle source
# File lib/familia/object.rb, line 435
def index
  case self.class.index
  when Proc
    self.class.index.call(self)
  when Array
    parts = self.class.index.collect { |meth| 
      unless self.respond_to? meth
        raise NoIndex, "No such method: `#{meth}' for #{self.class}"
      end
      ret = self.send(meth)
      ret = ret.index if ret.kind_of?(Familia)
      ret
    }
    parts.join Familia.delim
  when Symbol, String
    if self.class.redis_object?(self.class.index.to_sym)
      raise Familia::NoIndex, "Cannot use a RedisObject as an index"
    else
      unless self.respond_to? self.class.index
        raise NoIndex, "No such method: `#{self.class.index}' for #{self.class}"
      end
      ret = self.send(self.class.index)
      ret = ret.index if ret.kind_of?(Familia)
      ret
    end
  else
    raise Familia::NoIndex, self
  end
end
index=(v) click to toggle source
# File lib/familia/object.rb, line 464
def index=(v)
  case self.class.index
  when Proc
    raise ArgumentError, "Cannot set a Proc index"
  when Array
    unless Array === v && v.size == self.class.index.size
      raise ArgumentError, "Index mismatch (#{v.size} for #{self.class.index.size})"
    end
    parts = self.class.index.each_with_index { |meth,idx| 
      unless self.respond_to? "#{meth}="
        raise NoIndex, "No such method: `#{meth}=' for #{self.class}"
      end
      self.send("#{meth}=", v[idx]) 
    }
  when Symbol, String
    if self.class.redis_object?(self.class.index.to_sym)
      raise Familia::NoIndex, "Cannot use a RedisObject as an index"
    else
      unless self.respond_to? "#{self.class.index}="
        raise NoIndex, "No such method: `#{self.class.index}=' for #{self.class}"
      end
      self.send("#{self.class.index}=", v)
    end
  else
    raise Familia::NoIndex, self
  end
  
end
initialize_redis_objects() click to toggle source

This needs to be called in the initialize method of any class that includes Familia.

# File lib/familia/object.rb, line 319
def initialize_redis_objects
  # Generate instances of each RedisObject. These need to be
  # unique for each instance of this class so they can refer
  # to the index of this specific instance.
  #
  # i.e. 
  #     familia_object.rediskey              == v1:bone:INDEXVALUE:object
  #     familia_object.redis_object.rediskey == v1:bone:INDEXVALUE:name
  #
  # See RedisObject.install_redis_object
  self.class.redis_objects.each_pair do |name, redis_object_definition|
    klass, opts = redis_object_definition.klass, redis_object_definition.opts
    opts = opts.nil? ? {} : opts.clone
    opts[:parent] = self unless opts.has_key?(:parent)
    redis_object = klass.new name, opts
    redis_object.freeze
    self.instance_variable_set "@#{name}", redis_object
  end
end
object_proxy() click to toggle source
# File lib/familia/object.rb, line 392
def object_proxy
  @object_proxy ||= Familia::String.new self.rediskey, :ttl => ttl, :class => self.class
  @object_proxy
end
qstamp(quantum=nil, pattern=nil, now=Familia.now) click to toggle source
# File lib/familia/object.rb, line 339
def qstamp quantum=nil, pattern=nil, now=Familia.now
  self.class.qstamp ttl, pattern, now
end
raw(suffix=nil) click to toggle source
# File lib/familia/object.rb, line 505
def raw(suffix=nil)
  suffix ||= :object
  Familia.redis(self.class.uri).get rediskey(suffix)
end
realttl() click to toggle source
# File lib/familia/object.rb, line 496
def realttl
  Familia.redis(self.class.uri).ttl rediskey
end
redis() click to toggle source
# File lib/familia/object.rb, line 347
def redis
  self.class.redis
end
redisinfo() click to toggle source
# File lib/familia/object.rb, line 351
def redisinfo
  info = {
    :uri  => self.class.uri,
    :db   => self.class.db,
    :key  => rediskey,
    :type => redistype,
    :ttl  => realttl
  }
end
rediskey(suffix=nil, ignored=nil) click to toggle source

suffix is the value to be used at the end of the redis key + ignored+ is literally ignored. It's around to maintain consistency with the class version of this method. (RedisObject#rediskey may call against a class or instance).

# File lib/familia/object.rb, line 382
def rediskey(suffix=nil, ignored=nil)
  Familia.info "[#{self.class}] something was ignored" unless ignored.nil?
  raise Familia::NoIndex, self.class if index.to_s.empty?
  if suffix.nil?
    suffix = self.class.suffix.kind_of?(Proc) ? 
                 self.class.suffix.call(self) : 
                 self.class.suffix
  end
  self.class.rediskey self.index, suffix
end
redistype(suffix=nil) click to toggle source
# File lib/familia/object.rb, line 515
def redistype(suffix=nil)
  Familia.redis(self.class.uri).type rediskey(suffix)
end
redisuri(suffix=nil) click to toggle source
# File lib/familia/object.rb, line 509
def redisuri(suffix=nil)
  u = URI.parse self.class.uri.to_s
  u.db ||= self.class.db.to_s
  u.key = rediskey(suffix)
  u
end
save(meth=:set) click to toggle source
# File lib/familia/object.rb, line 396
def save meth=:set
  #Familia.trace :SAVE, Familia.redis(self.class.uri), redisuri, caller.first if Familia.debug?
  preprocess if respond_to?(:preprocess)
  self.update_time if self.respond_to?(:update_time)
  ret = object_proxy.send(meth, self)       # object is a name reserved by Familia
  unless ret.nil?
    now = Time.now.utc.to_i
    self.class.instances.add now, self     # use this set instead of Klass.keys
    object_proxy.update_expiration        # does nothing unless if not specified
  end
  ret == "OK" || ret == true || ret == 1
end
savenx() click to toggle source
# File lib/familia/object.rb, line 408
def savenx 
  save :setnx
end
shortid() click to toggle source

Finds the shortest available unique key (lower limit of 6)

# File lib/familia/object.rb, line 519
def shortid
  len = 6
  loop do
    begin
      self.class.expand(@id.shorten(len))
      break
    rescue Familia::NonUniqueKey
      len += 1
    end
  end
  @id.shorten(len) 
end
ttl() click to toggle source
# File lib/familia/object.rb, line 502
def ttl
  @ttl || self.class.ttl
end
ttl=(v) click to toggle source
# File lib/familia/object.rb, line 499
def ttl=(v)
  @ttl = v.to_i
end
update!(hsh=nil) click to toggle source
# File lib/familia/object.rb, line 411
def update! hsh=nil
  updated = false
  hsh ||= {}
  if hsh.empty?
    raise Familia::Problem, "No #{self.class}#{to_hash} method" unless respond_to?(:to_hash)
    ret = from_redis
    hsh = ret.to_hash if ret
  end
  hsh.keys.each { |field| 
    v = hsh[field.to_s] || hsh[field.to_s.to_sym]
    next if v.nil?
    self.send(:"#{field}=", v) 
    updated = true
  }
  updated
end