lib/ohm.rb in ohm-1.0.0.rc1 vs lib/ohm.rb in ohm-1.0.0.rc2

- old
+ new

@@ -18,11 +18,11 @@ # # Solution: you need to save your model first. # # IndexNotFound: # - # Comment.find(foo: "Bar") # => Error + # Comment.find(:foo => "Bar") # => Error # # Solution: add an index with `Comment.index :foo`. # # UniqueIndexViolation: # @@ -101,12 +101,12 @@ # Stores the connection options for the Redis instance. # # Examples: # - # Ohm.connect(port: 6380, db: 1, host: "10.0.1.1") - # Ohm.connect(url: "redis://10.0.1.1:6380/1") + # Ohm.connect(:port => 6380, :db => 1, :host => "10.0.1.1") + # Ohm.connect(:url => "redis://10.0.1.1:6380/1") # # All of the options are simply passed on to `Redis.connect`. # def self.connect(options = {}) conn.start(options) @@ -152,20 +152,20 @@ # # class User < Ohm::Model # attribute :name # end # - # User.all.sort_by(:name, order: "ALPHA") - # User.all.sort_by(:name, order: "ALPHA DESC") - # User.all.sort_by(:name, order: "ALPHA DESC", limit: [0, 10]) + # User.all.sort_by(:name, :order => "ALPHA") + # User.all.sort_by(:name, :order => "ALPHA DESC") + # User.all.sort_by(:name, :order => "ALPHA DESC", :limit => [0, 10]) # # Note: This is slower compared to just doing `sort`, specifically # because Redis has to read each individual hash in order to sort # them. # def sort_by(att, options = {}) - sort(options.merge(by: namespace["*->%s" % att])) + sort(options.merge(:by => namespace["*->%s" % att])) end # Allows you to sort your models using their IDs. This is much # faster than `sort_by`. If you simply want to get records in # ascending or descending order, then this is the best method to @@ -175,20 +175,20 @@ # # class User < Ohm::Model # attribute :name # end # - # User.create(name: "John") - # User.create(name: "Jane") + # User.create(:name => "John") + # User.create(:name => "Jane") # # User.all.sort.map(&:id) == ["1", "2"] # # => true # - # User.all.sort(order: "ASC").map(&:id) == ["1", "2"] + # User.all.sort(:order => "ASC").map(&:id) == ["1", "2"] # # => true # - # User.all.sort(order: "DESC").map(&:id) == ["2", "1"] + # User.all.sort(:order => "DESC").map(&:id) == ["2", "1"] # # => true # def sort(options = {}) if options.has_key?(:get) options[:get] = namespace["*->%s" % options[:get]] @@ -223,18 +223,18 @@ # first element. # # Example: # # User.all.first == - # User.all.sort(limit: [0, 1]).first + # User.all.sort(:limit => [0, 1]).first # - # User.all.first(by: :name, "ALPHA") == - # User.all.sort_by(:name, order: "ALPHA", limit: [0, 1]).first + # User.all.first(:by => :name, "ALPHA") == + # User.all.sort_by(:name, :order => "ALPHA", :limit => [0, 1]).first # def first(options = {}) opts = options.dup - opts.merge!(limit: [0, 1]) + opts.merge!(:limit => [0, 1]) if opts[:by] sort_by(opts.delete(:by), opts).first else sort(opts).first @@ -268,15 +268,19 @@ def fetch(ids) arr = model.db.pipelined do ids.each { |id| model.db.hgetall(namespace[id]) } end - return [] if arr.nil? + res = [] - arr.map.with_index do |atts, idx| - model.new(Hash[*atts].update(id: ids[idx])) + return res if arr.nil? + + arr.each_with_index do |atts, idx| + res << model.new(Hash[*atts].update(:id => ids[idx])) end + + res end end class List < Struct.new(:key, :namespace, :model) include Enumerable @@ -394,27 +398,31 @@ def fetch(ids) arr = model.db.pipelined do ids.each { |id| model.db.hgetall(namespace[id]) } end - return [] if arr.nil? + res = [] - arr.map.with_index do |atts, idx| - model.new(Hash[*atts].update(id: ids[idx])) + return res if arr.nil? + + arr.each_with_index do |atts, idx| + res << model.new(Hash[*atts].update(:id => ids[idx])) end + + res end end class Set < Struct.new(:key, :namespace, :model) include Collection # Chain new fiters on an existing set. # # Example: # - # set = User.find(name: "John") - # set.find(age: 30) + # set = User.find(:name => "John") + # set.find(:age => 30) # def find(dict) keys = model.filters(dict) keys.push(key) @@ -423,29 +431,29 @@ # Reduce the set using any number of filters. # # Example: # - # set = User.find(name: "John") - # set.except(country: "US") + # set = User.find(:name => "John") + # set.except(:country => "US") # # # You can also do it in one line. - # User.find(name: "John").except(country: "US") + # User.find(:name => "John").except(:country => "US") # def except(dict) MultiSet.new([key], namespace, model).except(dict) end # Do a union to the existing set using any number of filters. # # Example: # - # set = User.find(name: "John") - # set.union(name: "Jane") + # set = User.find(:name => "John") + # set.union(:name => "Jane") # # # You can also do it in one line. - # User.find(name: "John").union(name: "Jane") + # User.find(:name => "John").union(:name => "Jane") # def union(dict) MultiSet.new([key], namespace, model).union(dict) end @@ -517,25 +525,25 @@ # Example: # # User.all.kind_of?(Ohm::Set) # # => true # - # User.find(name: "John").kind_of?(Ohm::Set) + # User.find(:name => "John").kind_of?(Ohm::Set) # # => true # - # User.find(name: "John", age: 30).kind_of?(Ohm::MultiSet) + # User.find(:name => "John", :age => 30).kind_of?(Ohm::MultiSet) # # => true # class MultiSet < Struct.new(:keys, :namespace, :model) include Collection # Chain new fiters on an existing set. # # Example: # - # set = User.find(name: "John", age: 30) - # set.find(status: 'pending') + # set = User.find(:name => "John", :age => 30) + # set.find(:status => 'pending') # def find(dict) keys = model.filters(dict) keys.push(*self.keys) @@ -544,15 +552,15 @@ # Reduce the set using any number of filters. # # Example: # - # set = User.find(name: "John") - # set.except(country: "US") + # set = User.find(:name => "John") + # set.except(:country => "US") # # # You can also do it in one line. - # User.find(name: "John").except(country: "US") + # User.find(:name => "John").except(:country => "US") # def except(dict) sdiff.push(*model.filters(dict)).uniq! return self @@ -560,15 +568,15 @@ # Do a union to the existing set using any number of filters. # # Example: # - # set = User.find(name: "John") - # set.union(name: "Jane") + # set = User.find(:name => "John") + # set.union(:name => "Jane") # # # You can also do it in one line. - # User.find(name: "John").union(name: "Jane") + # User.find(:name => "John").union(:name => "Jane") # def union(dict) sunion.push(*model.filters(dict)).uniq! return self @@ -582,11 +590,11 @@ def sdiff @sdiff ||= [] end def execute - key = namespace[:temp][SecureRandom.uuid] + key = namespace[:temp][SecureRandom.hex(32)] key.sinterstore(*keys) key.sdiffstore(key, *sdiff) if sdiff.any? key.sunionstore(key, *sunion) if sunion.any? begin @@ -613,11 +621,11 @@ # counter :points # # set :posts, :Post # end # - # u = User.create(name: "John", email: "foo@bar.com") + # u = User.create(:name => "John", :email => "foo@bar.com") # u.incr :points # u.posts.add(Post.create) # # When you execute `User.create(...)`, you run the following Redis # commands: @@ -694,11 +702,11 @@ # u = User.create # u == User[u.id] # # => true # def self.[](id) - new(id: id).load! if id && exists?(id) + new(:id => id).load! if id && exists?(id) end # Retrieve a set of models given an array of IDs. # # Example: @@ -726,11 +734,11 @@ # # class User < Ohm::Model # unique :email # end # - # u = User.create(email: "foo@bar.com") + # u = User.create(:email => "foo@bar.com") # u == User.with(:email, "foo@bar.com") # # => true # def self.with(att, val) id = key[:uniques][att].hget(val) @@ -760,21 +768,21 @@ # def tag # ["ruby", "python"] # end # end # - # u = User.create(name: "John", status: "pending", email: "foo@me.com") - # User.find(provider: "me", name: "John", status: "pending").include?(u) + # u = User.create(:name => "John", :status => "pending", :email => "foo@me.com") + # User.find(:provider => "me", :name => "John", :status => "pending").include?(u) # # => true # - # User.find(tag: "ruby").include?(u) + # User.find(:tag => "ruby").include?(u) # # => true # - # User.find(tag: "python").include?(u) + # User.find(:tag => "python").include?(u) # # => true # - # User.find(tag: ["ruby", "python"]).include?(u) + # User.find(:tag => ["ruby", "python"]).include?(u) # # => true # def self.find(dict) keys = filters(dict) @@ -869,11 +877,11 @@ # # # is the same as # # class User < Ohm::Model # def posts - # Post.find(user_id: self.id) + # Post.find(:user_id => self.id) # end # end # def self.collection(name, model, reference = to_reference) define_method name do @@ -1022,11 +1030,11 @@ # # class User < Ohm::Model # attribute :name # end # - # u = User.create(name: "John") + # u = User.create(:name => "John") # u.key.hget(:name) # # => John # # For more details see # http://github.com/soveran/nest @@ -1037,11 +1045,11 @@ # Initialize a model using a dictionary of attributes. # # Example: # - # u = User.new(name: "John") + # u = User.new(:name => "John") # def initialize(atts = {}) @attributes = {} @_memo = {} update_attributes(atts) @@ -1088,11 +1096,11 @@ # the most recent value of the attribute and not rely on locally # cached value. # # Example: # - # User.create(name: "A") + # User.create(:name => "A") # # Session 1 | Session 2 # --------------|------------------------ # u = User[1] | u = User[1] # u.name = "B" | @@ -1158,27 +1166,27 @@ # # class User < Ohm::Model # attribute :name # end # - # u = User.create(name: "John") + # u = User.create(:name => "John") # u.to_hash - # # => { id: "1" } + # # => { :id => "1" } # # In order to add additional attributes, you can override `to_hash`: # # class User < Ohm::Model # attribute :name # # def to_hash - # super.merge(name: name) + # super.merge(:name => name) # end # end # - # u = User.create(name: "John") + # u = User.create(:name => "John") # u.to_hash - # # => { id: "1", name: "John" } + # # => { :id => "1", :name => "John" } # def to_hash attrs = {} attrs[:id] = id unless new? attrs[:errors] = errors if errors.any? @@ -1200,14 +1208,14 @@ # def validate # assert_present :name # end # end # - # User.new(name: nil).save + # User.new(:name => nil).save # # => nil # - # u = User.new(name: "John").save + # u = User.new(:name => "John").save # u.kind_of?(User) # # => true # def save(&block) return if not valid? @@ -1215,38 +1223,46 @@ end # Saves the model without checking for validity. Refer to # `Model#save` for more details. def save! - transaction do |t| + t = __save__ + yield t if block_given? + t.commit(db) + + return self + end + + def __save__ + Transaction.new do |t| t.watch(*_unique_keys) t.watch(key) if not new? t.before do _initialize_id if new? end - t.read do |store| + existing = nil + uniques = nil + indices = nil + + t.read do _verify_uniques - store.existing = key.hgetall - store.uniques = _read_index_type(:uniques) - store.indices = _read_index_type(:indices) + existing = key.hgetall + uniques = _read_index_type(:uniques) + indices = _read_index_type(:indices) end - t.write do |store| + t.write do model.key[:all].sadd(id) - _delete_uniques(store.existing) - _delete_indices(store.existing) + _delete_uniques(existing) + _delete_indices(existing) _save - _save_indices(store.indices) - _save_uniques(store.uniques) + _save_indices(indices) + _save_uniques(uniques) end - - yield t if block_given? end - - return self end # Delete the model, including all the following keys: # # - <Model>:<id> @@ -1256,16 +1272,16 @@ # If the model has uniques or indices, they're also cleaned up. # def delete transaction do |t| t.read do |store| - store.existing = key.hgetall + store[:existing] = key.hgetall end t.write do |store| - _delete_uniques(store.existing) - _delete_indices(store.existing) + _delete_uniques(store[:existing]) + _delete_indices(store[:existing]) model.collections.each { |e| key[e].del } model.key[:all].srem(id) key[:counters].del key.del end @@ -1276,16 +1292,16 @@ # Update the model attributes and call save. # # Example: # - # User[1].update(name: "John") + # User[1].update(:name => "John") # # # It's the same as: # # u = User[1] - # u.update_attributes(name: "John") + # u.update_attributes(:name => "John") # u.save # def update(attributes) update_attributes(attributes) save @@ -1374,11 +1390,11 @@ end def _save catch :empty do key.del - key.hmset(*_skip_empty(attributes).flatten) + key.hmset(*_skip_empty(attributes).to_a.flatten) end end def _verify_uniques if att = _detect_duplicate @@ -1451,13 +1467,15 @@ def run(script, options) keys = options[:keys] argv = options[:argv] + params = keys + argv + begin - redis.evalsha(sha(script), keys.size, *keys, *argv) + redis.evalsha(sha(script), keys.size, *params) rescue RuntimeError - redis.eval(script, keys.size, *keys, *argv) + redis.eval(script, keys.size, *params) end end private def read(file)