class Findable::Query

Attributes

model[R]

Public Class Methods

new(model, serializer = nil) click to toggle source
# File lib/findable/query.rb, line 13
def initialize(model, serializer = nil)
  @model = model
  @serializer = serializer || Serializer.new
end

Public Instance Methods

all() click to toggle source
# File lib/findable/query.rb, line 18
def all
  @serializer.deserialize(redis.hvals(data_key), model)
end
count() click to toggle source
# File lib/findable/query.rb, line 26
def count
  redis.hlen(data_key)
end
delete(object) click to toggle source
# File lib/findable/query.rb, line 81
def delete(object)
  if model.index_defined?
    model.indexes.each do |name|
      next if name == :id
      if value = object.public_send("#{name}_was") || object.public_send(name)
        redis.hdel(index_key, value)
      end
    end
  end

  redis.hdel(data_key, object.id)
end
delete_all() click to toggle source
# File lib/findable/query.rb, line 94
def delete_all
  redis.multi do
    [data_key, info_key, index_key].each {|key| redis.del(key) }
  end
end
exists?(id) click to toggle source
# File lib/findable/query.rb, line 40
def exists?(id)
  redis.hexists(data_key, id)
end
find_by_ids(ids) click to toggle source
# File lib/findable/query.rb, line 30
def find_by_ids(ids)
  @serializer.deserialize(redis.hmget(data_key, *Array(ids)), model)
end
find_by_index(index, value) click to toggle source
# File lib/findable/query.rb, line 34
def find_by_index(index, value)
  if ids = ids_from_index([index, value].join(":"))
    find_by_ids(ids)
  end
end
ids() click to toggle source
# File lib/findable/query.rb, line 22
def ids
  redis.hkeys(data_key).map(&:to_i)
end
import(hashes) click to toggle source
# File lib/findable/query.rb, line 57
def import(hashes)
  lock do
    indexes = Hash.new {|h, k| h[k] = [] }
    values = hashes.each_with_object([]) do |hash, obj|
      hash = hash.with_indifferent_access
      hash["id"] = auto_incremented_id(hash["id"])
      obj << hash["id"]
      obj << @serializer.serialize(hash)

      if model.index_defined?
        model.indexes.each_with_object([]) do |name, obj|
          next if name == :id
          indexes[[name, hash[name]].join(":")] << hash["id"]
        end
      end
    end
    redis.hmset(data_key, *values)
    if indexes.present?
      attrs = indexes.map {|k, v| [k, @serializer.serialize(v)] }.flatten
      redis.hmset(index_key, *attrs)
    end
  end
end
insert(object) click to toggle source
# File lib/findable/query.rb, line 44
def insert(object)
  lock do
    object.id = auto_incremented_id(object.id)
    redis.hset(
      data_key,
      object.id,
      @serializer.serialize(object.attributes)
    )
    update_index(object)
  end
  object
end
lock() { || ... } click to toggle source
# File lib/findable/query.rb, line 100
def lock
  raise ArgumentError, "Require block" unless block_given?
  Lock.new(lock_key, thread_key).lock { yield }
end
update_index(object) click to toggle source
# File lib/findable/query.rb, line 105
def update_index(object)
  if model.index_defined?
    indexes = model.indexes.each_with_object([]) {|name, obj|
      next if name == :id || object.public_send("#{name}_changed?")

      if old_value = object.public_send("#{name}_was")
        old_index_key = [name, old_value].join(":")

        if (old_ids = ids_from_index(old_index_key)).present?
          new_ids = old_ids.reject {|id| id == object.id }
          if new_ids.empty?
            redis.hdel(index_key, old_index_key)
          else
            obj << old_index_key
            obj << @serializer.serialize(new_ids)
          end
        end
      end

      obj << [name, object.public_send(name)].join(":")
      obj << object.id
    }
    redis.hmset(index_key, *indexes)
  end
end

Private Instance Methods

auto_incremented_id(id) click to toggle source
# File lib/findable/query.rb, line 132
def auto_incremented_id(id)
  if id.present?
    current = redis.hget(info_key, AUTO_INCREMENT_KEY).to_i
    id = id.to_i
    if id > current
      redis.hset(info_key, AUTO_INCREMENT_KEY, id)
    end
    id
  else
    redis.hincrby(info_key, AUTO_INCREMENT_KEY, 1)
  end
end
ids_from_index(index_name) click to toggle source
# File lib/findable/query.rb, line 145
def ids_from_index(index_name)
  if ids = redis.hget(index_key, index_name)
    @serializer.deserialize(ids)
  end
end