Permalink
Browse files

Adding more tests. Renamed CriteriaMerger to CriteriaHash and simplif…

…ied merge process.
  • Loading branch information...
1 parent ae3651e commit 532c48a282b62ea9788d6247eac9c128bf1abdfb @jnunemaker jnunemaker committed May 8, 2010
View
@@ -17,7 +17,7 @@ class Symbol
end
module Plucky
- autoload :CriteriaMerger, 'plucky/criteria_merger'
+ autoload :CriteriaHash, 'plucky/criteria_hash'
autoload :Query, 'plucky/query'
def self.to_object_id(value)
@@ -0,0 +1,27 @@
+module Plucky
+ class CriteriaHash
+ attr_reader :hash
+
+ def initialize(hash)
+ @hash = hash
+ end
+
+ def merge(other)
+ hash.dup.tap do |target|
+ other.keys.each do |key|
+ value, other_value = target[key], other[key]
+ target[key] =
+ if target.key?(key)
+ if value.is_a?(Hash)
+ self.class.new(value).merge(other_value)
+ else
+ Array(value).concat(Array(other_value)).uniq
+ end
+ else
+ other_value
+ end
+ end
+ end
+ end
+ end
+end
@@ -1,23 +0,0 @@
-module Plucky
- class CriteriaMerger
- def self.merge(hash, other)
- hash.dup.tap do |target|
- other.keys.each do |key|
- if target[key].is_a?(Hash)
- if other[key].is_a?(Hash)
- target[key] = merge(target[key], other[key])
- else
- target[key]['$in'].concat(Array(other[key])).uniq!
- end
- else
- if target.key?(key) && other.key?(key)
- target[key] = Array(target[key]).concat(Array(other[key]))
- else
- target[key] = other[key]
- end
- end
- end
- end
- end
- end
-end
View
@@ -80,7 +80,8 @@ def sort(*args)
end
def where(hash={})
- @criteria.update(CriteriaMerger.merge(@criteria, normalized_criteria(hash)))
+ merged_criteria = CriteriaHash.new(@criteria).merge(normalized_criteria(hash))
+ @criteria.update(normalized_criteria(merged_criteria))
self
end
View
@@ -18,4 +18,8 @@ def oh(*args)
args.each { |a| hash[a[0]] = a[1] }
end
end
-end
+end
+
+operators = %w{gt lt gte lte ne in nin mod all size exists}
+operators.delete('size') if RUBY_VERSION >= '1.9.1'
+SymbolOperators = operators
@@ -0,0 +1,39 @@
+require 'helper'
+
+class CriteriaHashTest < Test::Unit::TestCase
+ include Plucky
+
+ context "Plucky::CriteriaHash" do
+ context ".merge" do
+ should "work when no keys match" do
+ first, second = {:foo => 'bar'}, {:baz => 'wick'}
+ CriteriaHash.new(first).merge(second).should == {
+ :foo => 'bar',
+ :baz => 'wick',
+ }
+ end
+
+ should "turn matching keys with simple values into array" do
+ first, second = {:foo => 'bar'}, {:foo => 'baz'}
+ CriteriaHash.new(first).merge(second).should == {
+ :foo => %w[bar baz],
+ }
+ end
+
+ should "unique matching key values" do
+ first, second = {:foo => 'bar'}, {:foo => %w(bar baz)}
+ CriteriaHash.new(first).merge(second).should == {
+ :foo => %w[bar baz],
+ }
+ end
+
+ should "turn matching keys with $in => arrays to one $in => array of uniq values" do
+ first = {:foo => {'$in' => [1, 2, 3]}}
+ second = {:foo => {'$in' => [1, 4, 5]}}
+ CriteriaHash.new(first).merge(second).should == {
+ :foo => {'$in' => [1, 2, 3, 4, 5]}
+ }
+ end
+ end
+ end
+end
@@ -1,17 +1,17 @@
require 'helper'
class QueryTest < Test::Unit::TestCase
- context "Plucky::Query" do
+ context "Query" do
include Plucky
setup do
@chris = oh(['_id', 'chris'], ['age', 26], ['name', 'Chris'])
- @john = oh(['_id', 'john'], ['age', 28], ['name', 'John'])
@steve = oh(['_id', 'steve'], ['age', 29], ['name', 'Steve'])
+ @john = oh(['_id', 'john'], ['age', 28], ['name', 'John'])
@collection = DB['users']
- @collection.insert(:_id => 'john', :age => 28, :name => 'John')
- @collection.insert(:_id => 'steve', :age => 29, :name => 'Steve')
- @collection.insert(:_id => 'chris', :age => 26, :name => 'Chris')
+ @collection.insert(@chris)
+ @collection.insert(@steve)
+ @collection.insert(@john)
end
context "#find" do
@@ -63,7 +63,7 @@ class QueryTest < Test::Unit::TestCase
context "#first" do
should "work with and normalize criteria" do
- Query.new(@collection).first(:age.lt => 29).should == @john
+ Query.new(@collection).first(:age.lt => 29).should == @chris
end
should "work with and normalize options" do
@@ -162,22 +162,6 @@ class QueryTest < Test::Unit::TestCase
end
end
- context "#where" do
- should "work" do
- Query.new(@collection).where(:age.lt => 29).where(:name => 'Chris').all.should == [@chris]
- end
-
- should "update criteria" do
- Query.new(@collection, :moo => 'cow').where(:foo => 'bar').criteria.should == {:foo => 'bar', :moo => 'cow'}
- end
-
- should "get normalized" do
- Query.new(@collection, :moo => 'cow').where(:foo.in => ['bar']).criteria.should == {
- :moo => 'cow', :foo => {'$in' => ['bar']}
- }
- end
- end
-
context "#skip" do
should "work" do
Query.new(@collection).skip(2).all(:order => :age).should == [@steve]
@@ -257,6 +241,28 @@ class QueryTest < Test::Unit::TestCase
end
end
+ context "#where" do
+ should "work" do
+ Query.new(@collection).where(:age.lt => 29).where(:name => 'Chris').all.should == [@chris]
+ end
+
+ should "update criteria" do
+ Query.new(@collection, :moo => 'cow').where(:foo => 'bar').criteria.should == {:foo => 'bar', :moo => 'cow'}
+ end
+
+ should "get normalized" do
+ Query.new(@collection, :moo => 'cow').where(:foo.in => ['bar']).criteria.should == {
+ :moo => 'cow', :foo => {'$in' => ['bar']}
+ }
+ end
+
+ should "normalize merged criteria" do
+ Query.new(@collection).where(:foo => 'bar').where(:foo => 'baz').criteria.should == {
+ :foo => {'$in' => %w[bar baz]}
+ }
+ end
+ end
+
context "#merge" do
should "overwrite options" do
query1 = Query.new(@collection, :skip => 5, :limit => 5)
@@ -266,34 +272,16 @@ class QueryTest < Test::Unit::TestCase
new_query.options[:limit].should == 10
end
- should "merge when no criteria match" do
+ should "merge criteria" do
query1 = Query.new(@collection, :foo => 'bar')
- query2 = Query.new(@collection, :baz => 'wick')
+ query2 = Query.new(@collection, :foo => 'baz', :fent => 'wick')
new_query = query1.merge(query2)
- new_query.criteria.should == {:foo => 'bar', :baz => 'wick'}
- end
-
- should "merge exact matches to $in with array" do
- query1 = Query.new(@collection, :foo => 'bar')
- query2 = Query.new(@collection, :foo => 'baz')
- query3 = Query.new(@collection, :foo => 'wick')
- new_query = query1.merge(query2).merge(query3)
- new_query.criteria.should == {:foo => {'$in' => ['bar', 'baz', 'wick']}}
- end
-
- should "merge $in arrays" do
- query1 = Query.new(@collection, :foo.in => [1, 2])
- query2 = Query.new(@collection, :foo.in => [3, 4, 5])
- query3 = Query.new(@collection, :foo.in => [6])
- new_query = query1.merge(query2).merge(query3)
- new_query.criteria.should == {:foo => {'$in' => [1, 2, 3, 4, 5, 6]}}
+ new_query.criteria.should == {:foo => {'$in' => %w[bar baz]}, :fent => 'wick'}
end
end
context "Converting criteria" do
- %w{gt lt gte lte ne in nin mod all size exists}.each do |operator|
- next if operator == 'size' && RUBY_VERSION >= '1.9.1' # 1.9 defines Symbol#size
-
+ SymbolOperators.each do |operator|
should "work with #{operator} symbol operator" do
Query.new(@collection, :age.send(operator) => 21).criteria.should == {:age => {"$#{operator}" => 21}}
end
View
@@ -0,0 +1,11 @@
+require 'helper'
+
+class SymbolTest < Test::Unit::TestCase
+ context "Symbol" do
+ SymbolOperators.each do |operator|
+ should "respond to #{operator}" do
+ :foo.send(operator).should be_instance_of(SymbolOperator)
+ end
+ end
+ end
+end
@@ -0,0 +1,16 @@
+require 'helper'
+
+class SymbolOperatorTest < Test::Unit::TestCase
+ context "SymbolOperator" do
+ setup { @operator = SymbolOperator.new(:foo, 'in') }
+ subject { @operator }
+
+ should "have field" do
+ subject.field.should == :foo
+ end
+
+ should "have operator" do
+ subject.operator.should == 'in'
+ end
+ end
+end

0 comments on commit 532c48a

Please sign in to comment.