lib/ohm.rb in ohm-0.0.38 vs lib/ohm.rb in ohm-0.1.0.rc1
- old
+ new
@@ -7,11 +7,11 @@
require File.join(File.dirname(__FILE__), "ohm", "compat-1.8.6")
require File.join(File.dirname(__FILE__), "ohm", "key")
require File.join(File.dirname(__FILE__), "ohm", "collection")
module Ohm
- VERSION = "0.0.38"
+ VERSION = "0.1.0.rc1"
# Provides access to the Redis database. This is shared accross all models and instances.
def redis
threaded[:redis] ||= connection(*options)
end
@@ -147,14 +147,14 @@
#
# user = User.all.sort_by(:name, :order => "ALPHA").first
# user.name == "A"
# # => true
def sort_by(att, options = {})
- options.merge!(:by => model.key("*", att))
+ options.merge!(:by => model.key("*->#{att}"))
if options[:get]
- raw.sort(options.merge(:get => model.key("*", options[:get])))
+ raw.sort(options.merge(:get => model.key("*->#{options[:get]}")))
else
sort(options)
end
end
@@ -198,11 +198,11 @@
class Set < Collection
Raw = Ohm::Set
def inspect
- "#<Set (#{model}): #{raw.to_a.inspect}>"
+ "#<Set (#{model}): #{all.inspect}>"
end
# Returns an intersection with the sets generated from the passed hash.
#
# @see Ohm::Model.find
@@ -210,27 +210,28 @@
# @events = Event.find(public: true)
#
# # You can combine the result with sort and other set operations:
# @events.sort_by(:name)
def find(hash)
- apply(:sinterstore, hash, "+")
+ apply(:sinterstore, hash, :+)
end
# Returns the difference between the receiver and the passed sets.
#
# @example
# @events = Event.find(public: true).except(status: "sold_out")
def except(hash)
- apply(:sdiffstore, hash, "-")
+ apply(:sdiffstore, hash, :-)
end
private
- # Apply a redis operation on a collection of sets.
+ # Apply a Redis operation on a collection of sets.
def apply(operation, hash, glue)
- target = key.volatile.group(glue).append(*keys(hash))
- model.db.send(operation, target, *target.sub_keys)
+ keys = keys(hash)
+ target = key.volatile.send(glue, Key[*keys])
+ model.db.send(operation, target, key, *keys)
Set.new(target, Wrapper.wrap(model))
end
# Transform a hash of attribute/values into an array of keys.
def keys(hash)
@@ -263,11 +264,11 @@
def unshift(model)
raw.unshift(model.id)
end
def inspect
- "#<List (#{model}): #{raw.to_a.inspect}>"
+ "#<List (#{model}): #{all.inspect}>"
end
end
class Index < Set
def apply(operation, hash, glue)
@@ -288,11 +289,11 @@
# @overload assert_unique :name
# Validates that the name attribute is unique.
# @overload assert_unique [:street, :city]
# Validates that the :street and :city pair is unique.
def assert_unique(attrs)
- result = db.sinter(*Array(attrs).map { |att| index_key_for(att, send(att)) }) || []
+ result = db.sinter(*Array(attrs).map { |att| index_key_for(att, send(att)) })
assert result.empty? || !new? && result.include?(id.to_s), [attrs, :not_unique]
end
end
include Validations
@@ -488,11 +489,11 @@
model = Wrapper.wrap(model)
define_method(name) { model.unwrap.find(:"#{reference}_id" => send(:id)) }
end
def self.to_reference
- name.to_s.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym
+ name.to_s.match(/^(?:.*::)*(.*)$/)[1].gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym
end
def self.attr_collection_reader(name, type, model)
if model
model = Wrapper.wrap(model)
@@ -600,31 +601,28 @@
end
end
def delete
delete_from_indices
- delete_attributes(attributes)
- delete_attributes(counters)
- delete_attributes(collections)
+ delete_attributes(collections) unless collections.empty?
delete_model_membership
self
end
# Increment the counter denoted by :att.
#
# @param att [Symbol] Attribute to increment.
- def incr(att)
+ def incr(att, count = 1)
raise ArgumentError, "#{att.inspect} is not a counter." unless counters.include?(att)
- write_local(att, db.incr(key(att)))
+ write_local(att, db.hincrby(key, att, count))
end
# Decrement the counter denoted by :att.
#
# @param att [Symbol] Attribute to decrement.
- def decr(att)
- raise ArgumentError, "#{att.inspect} is not a counter." unless counters.include?(att)
- write_local(att, db.decr(key(att)))
+ def decr(att, count = 1)
+ incr(att, -count)
end
def attributes
self.class.attributes
end
@@ -693,30 +691,26 @@
def key(*args)
self.class.key(id, *args)
end
- # Write attributes using MSET
def write
unless attributes.empty?
- rems, adds = attributes.map { |a| [key(a), send(a)] }.partition { |t| t.last.to_s.empty? }
+ attributes.each_with_index do |att, index|
+ value = send(att).to_s
- db.del(*rems.flatten.compact) unless rems.empty?
- db.mapped_mset(adds.flatten) unless adds.empty?
+ if value.empty?
+ db.hdel(key, att)
+ else
+ db.hset(key, att, value)
+ end
+ end
end
end
def self.const_missing(name)
- wrapper = Wrapper.new(name) { const_get(name) }
-
- # Allow others to hook to const_missing.
- begin
- super(name)
- rescue NameError
- end
-
- wrapper
+ Wrapper.new(name) { const_get(name) }
end
private
# Provides access to the Redis database. This is shared accross all models and instances.
@@ -743,21 +737,20 @@
def db
self.class.db
end
def delete_attributes(atts)
- atts.each do |att|
- db.del(key(att))
- end
+ db.del(*atts.map { |att| key(att) })
end
def create_model_membership
- db.sadd(self.class.key(:all), id)
+ self.class.all << self
end
def delete_model_membership
- db.srem(self.class.key(:all), id)
+ db.del(key)
+ self.class.all.delete(self)
end
def update_indices
delete_from_indices
add_to_indices
@@ -784,11 +777,11 @@
db.sadd(index, id)
db.sadd(key(:_indices), index)
end
def delete_from_indices
- (db.smembers(key(:_indices)) || []).each do |index|
+ db.smembers(key(:_indices)).each do |index|
db.srem(index, id)
end
db.del(key(:_indices))
end
@@ -801,10 +794,10 @@
@_attributes[att] = value
end
def read_remote(att)
unless new?
- value = db.get(key(att))
+ value = db.hget(key, att)
value.respond_to?(:force_encoding) ?
value.force_encoding("UTF-8") :
value
end
end