lib/ohm.rb in ohm-0.0.11 vs lib/ohm.rb in ohm-0.0.12
- old
+ new
@@ -2,11 +2,11 @@
require File.join(File.dirname(__FILE__), "ohm", "redis")
require File.join(File.dirname(__FILE__), "ohm", "validations")
module Ohm
- # Provides access to the redis database. This is shared accross all models and instances.
+ # Provides access to the Redis database. This is shared accross all models and instances.
def redis
@redis
end
# Connect to a redis database.
@@ -36,22 +36,61 @@
module Attributes
class Collection
include Enumerable
- attr_accessor :key, :db
+ attr_accessor :key, :db, :model
- def initialize(db, key)
+ def initialize(db, key, model = nil)
self.db = db
self.key = key
+ self.model = model
end
def each(&block)
all.each(&block)
end
- def all(model = nil)
+ # Return instances of model for all the ids contained in the collection.
+ def all
+ instantiate(raw)
+ end
+
+ # Return the values as model instances, ordered by the options supplied.
+ # Check redis documentation to see what values you can provide to each option.
+ #
+ # @param options [Hash] options to sort the collection.
+ # @option options [#to_s] :by Model attribute to sort the instances by.
+ # @option options [#to_s] :order (ASC) Sorting order, which can be ASC or DESC.
+ # @option options [Integer] :limit (all) Number of items to return.
+ # @option options [Integer] :start (0) An offset from where the limit will be applied.
+ # @example Get the first ten users sorted alphabetically by name:
+ # @event.attendees.sort(User, :by => :name, :order => "ALPHA", :limit => 10)
+ #
+ # @example Get five posts sorted by number of votes and starting from the number 5 (zero based):
+ # @blog.posts.sort(Post, :by => :votes, :start => 5, :limit => 10")
+ def sort(options = {})
+ options[:start] ||= 0
+ options[:limit] = [options[:start], options[:limit]] if options[:limit]
+ instantiate(db.sort(key, options))
+ end
+
+ def sort_by(att, options = {})
+ sort(options.merge(:by => model.key("*", att)))
+ end
+
+ def to_ary
+ all
+ end
+
+ def ==(other)
+ to_ary == other
+ end
+
+ private
+
+ def instantiate(raw)
model ? raw.collect { |id| model[id] } : raw
end
end
# Represents a Redis list.
@@ -72,11 +111,13 @@
# @param value [#to_s] Pushes value to the list.
def << value
db.rpush(key, value)
end
- private
+ def empty?
+ db.llen(key).zero?
+ end
def raw
db.list(key)
end
end
@@ -111,18 +152,20 @@
def delete(value)
db.srem(key, value)
end
+ def empty?
+ db.scard(key).zero?
+ end
+
def include?(value)
db.sismember(key, value)
end
- private
-
def raw
- db.smembers(key).sort
+ db.smembers(key)
end
end
end
class Model
@@ -183,22 +226,22 @@
# Defines a list attribute for the model. It can be accessed only after the model instance
# is created.
#
# @param name [Symbol] Name of the list.
- def self.list(name)
- attr_list_reader(name)
+ def self.list(name, model = nil)
+ attr_list_reader(name, model)
collections << name
end
# Defines a set attribute for the model. It can be accessed only after the model instance
# is created. Sets are recommended when insertion and retrival order is irrelevant, and
# operations like union, join, and membership checks are important.
#
# @param name [Symbol] Name of the set.
- def self.set(name)
- attr_set_reader(name)
+ def self.set(name, model = nil)
+ attr_set_reader(name, model)
collections << name
end
# Creates an index (a set) that will be used for finding instances.
#
@@ -223,32 +266,30 @@
# Creates a composite index for street and city.
def self.index(attrs)
indices << Array(attrs)
end
- def self.attr_list_reader(name)
- class_eval <<-EOS
- def #{name}
- @#{name} ||= Attributes::List.new(db, key("#{name}"))
- end
- EOS
+ def self.attr_list_reader(name, model = nil)
+ define_method(name) do
+ instance_variable_get("@#{name}") ||
+ instance_variable_set("@#{name}", Attributes::List.new(db, key(name), model))
+ end
end
- def self.attr_set_reader(name)
- class_eval <<-EOS
- def #{name}
- @#{name} ||= Attributes::Set.new(db, key("#{name}"))
- end
- EOS
+ def self.attr_set_reader(name, model)
+ define_method(name) do
+ instance_variable_get("@#{name}") ||
+ instance_variable_set("@#{name}", Attributes::Set.new(db, key(name), model))
+ end
end
def self.[](id)
new(:id => id) if exists?(id)
end
def self.all
- filter(:all)
+ @all ||= Attributes::Set.new(db, key(:all), self)
end
def self.attributes
@@attributes[self]
end
@@ -270,11 +311,11 @@
model.create
model
end
def self.find(attribute, value)
- filter(Ohm.key(attribute, encode(value)))
+ Attributes::Set.new(db, key(attribute, encode(value)), self)
end
def self.encode(value)
Base64.encode64(value.to_s).chomp
end
@@ -372,15 +413,9 @@
Ohm.redis
end
def self.key(*args)
Ohm.key(*args.unshift(self))
- end
-
- def self.filter(name)
- db.smembers(key(name)).map do |id|
- new(:id => id)
- end
end
def self.exists?(id)
db.sismember(key(:all), id)
end