plucky 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.bundle/config +4 -0
  2. data/.gitignore +3 -1
  3. data/.travis.yml +2 -2
  4. data/Gemfile +13 -3
  5. data/Guardfile +13 -0
  6. data/README.md +1 -1
  7. data/Rakefile +3 -17
  8. data/examples/query.rb +1 -1
  9. data/lib/plucky.rb +13 -0
  10. data/lib/plucky/criteria_hash.rb +85 -56
  11. data/lib/plucky/normalizers/criteria_hash_key.rb +17 -0
  12. data/lib/plucky/normalizers/criteria_hash_value.rb +83 -0
  13. data/lib/plucky/normalizers/fields_value.rb +26 -0
  14. data/lib/plucky/normalizers/integer.rb +19 -0
  15. data/lib/plucky/normalizers/options_hash_key.rb +23 -0
  16. data/lib/plucky/normalizers/options_hash_value.rb +85 -0
  17. data/lib/plucky/normalizers/sort_value.rb +55 -0
  18. data/lib/plucky/options_hash.rb +56 -85
  19. data/lib/plucky/pagination/decorator.rb +3 -2
  20. data/lib/plucky/pagination/paginator.rb +15 -6
  21. data/lib/plucky/query.rb +93 -51
  22. data/lib/plucky/version.rb +1 -1
  23. data/script/criteria_hash.rb +21 -0
  24. data/{test → spec}/helper.rb +12 -8
  25. data/spec/plucky/criteria_hash_spec.rb +166 -0
  26. data/spec/plucky/normalizers/criteria_hash_key_spec.rb +37 -0
  27. data/spec/plucky/normalizers/criteria_hash_value_spec.rb +193 -0
  28. data/spec/plucky/normalizers/fields_value_spec.rb +45 -0
  29. data/spec/plucky/normalizers/integer_spec.rb +24 -0
  30. data/spec/plucky/normalizers/options_hash_key_spec.rb +23 -0
  31. data/spec/plucky/normalizers/options_hash_value_spec.rb +99 -0
  32. data/spec/plucky/normalizers/sort_value_spec.rb +94 -0
  33. data/spec/plucky/options_hash_spec.rb +64 -0
  34. data/{test/plucky/pagination/test_decorator.rb → spec/plucky/pagination/decorator_spec.rb} +8 -10
  35. data/spec/plucky/pagination/paginator_spec.rb +118 -0
  36. data/spec/plucky/query_spec.rb +839 -0
  37. data/spec/plucky_spec.rb +68 -0
  38. data/{test/test_symbol_operator.rb → spec/symbol_operator_spec.rb} +14 -16
  39. data/spec/symbol_spec.rb +9 -0
  40. metadata +58 -23
  41. data/test/plucky/pagination/test_paginator.rb +0 -120
  42. data/test/plucky/test_criteria_hash.rb +0 -359
  43. data/test/plucky/test_options_hash.rb +0 -302
  44. data/test/plucky/test_query.rb +0 -843
  45. data/test/test_plucky.rb +0 -48
  46. data/test/test_symbol.rb +0 -11
@@ -0,0 +1,68 @@
1
+ require 'helper'
2
+
3
+ describe Plucky do
4
+ describe ".to_object_id" do
5
+ before do
6
+ @id = BSON::ObjectId.new
7
+ end
8
+
9
+ it "converts nil to nil" do
10
+ Plucky.to_object_id(nil).should be_nil
11
+ end
12
+
13
+ it "converts blank to nil" do
14
+ Plucky.to_object_id('').should be_nil
15
+ end
16
+
17
+ it "leaves object id alone" do
18
+ Plucky.to_object_id(@id).should equal(@id)
19
+ end
20
+
21
+ it "converts string to object id" do
22
+ Plucky.to_object_id(@id.to_s).should == @id
23
+ end
24
+
25
+ it "not convert string that is not legal object id" do
26
+ Plucky.to_object_id('foo').should == 'foo'
27
+ Plucky.to_object_id(1).should == 1
28
+ end
29
+ end
30
+
31
+ describe ".modifier?" do
32
+ context "with a string" do
33
+ it "returns true if modifier" do
34
+ Plucky.modifier?('$in').should be_true
35
+ end
36
+
37
+ it "returns false if not modifier" do
38
+ Plucky.modifier?('nope').should be_false
39
+ end
40
+ end
41
+
42
+ context "with a symbol" do
43
+ it "returns true if modifier" do
44
+ Plucky.modifier?(:$in).should be_true
45
+ end
46
+
47
+ it "returns false if not modifier" do
48
+ Plucky.modifier?(:nope).should be_false
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "::Methods" do
54
+ it "returns array of methods" do
55
+ Plucky::Methods.should == [
56
+ :where, :filter,
57
+ :sort, :order, :reverse,
58
+ :paginate, :per_page, :limit, :skip, :offset,
59
+ :fields, :ignore, :only,
60
+ :each, :find_each, :find_one, :find,
61
+ :count, :size, :distinct,
62
+ :last, :first, :all, :to_a,
63
+ :exists?, :exist?, :empty?,
64
+ :remove,
65
+ ].sort_by(&:to_s)
66
+ end
67
+ end
68
+ end
@@ -1,55 +1,53 @@
1
1
  require 'helper'
2
2
 
3
- class SymbolOperatorTest < Test::Unit::TestCase
3
+ describe SymbolOperator do
4
4
  context "SymbolOperator" do
5
- setup { @operator = SymbolOperator.new(:foo, 'in') }
5
+ before { @operator = SymbolOperator.new(:foo, 'in') }
6
6
  subject { @operator }
7
7
 
8
- should "have field" do
8
+ it "has field" do
9
9
  subject.field.should == :foo
10
10
  end
11
11
 
12
- should "have operator" do
12
+ it "has operator" do
13
13
  subject.operator.should == 'in'
14
14
  end
15
15
 
16
16
  context "==" do
17
- should "be true if field and operator are equal" do
17
+ it "returns true if field and operator are equal" do
18
18
  SymbolOperator.new(:foo, 'in').should == SymbolOperator.new(:foo, 'in')
19
19
  end
20
20
 
21
- should "be false if fields are equal but operators are not" do
21
+ it "returns false if fields are equal but operators are not" do
22
22
  SymbolOperator.new(:foo, 'in').should_not == SymbolOperator.new(:foo, 'all')
23
23
  end
24
24
 
25
- should "be false if operators are equal but fields are not" do
25
+ it "returns false if operators are equal but fields are not" do
26
26
  SymbolOperator.new(:foo, 'in').should_not == SymbolOperator.new(:bar, 'in')
27
27
  end
28
28
 
29
- should "be false if neither are equal" do
29
+ it "returns false if neither are equal" do
30
30
  SymbolOperator.new(:foo, 'in').should_not == SymbolOperator.new(:bar, 'all')
31
31
  end
32
32
 
33
- should "be false if other isn't an symbol operator" do
34
- assert_nothing_raised do
35
- SymbolOperator.new(:foo, 'in').should_not == 'foo.in'
36
- end
33
+ it "returns false if other isn't an symbol operator" do
34
+ SymbolOperator.new(:foo, 'in').should_not == 'foo.in'
37
35
  end
38
36
  end
39
37
 
40
38
  context "<=>" do
41
- should "same field, different operator" do
39
+ it "returns string comparison of operator for same field, different operator" do
42
40
  (SymbolOperator.new(:foo, 'in') <=> SymbolOperator.new(:foo, 'all')).should == 1
43
41
  (SymbolOperator.new(:foo, 'all') <=> SymbolOperator.new(:foo, 'in')).should == -1
44
42
  end
45
43
 
46
- should "same field same operator" do
44
+ it "returns 0 for same field same operator" do
47
45
  (SymbolOperator.new(:foo, 'in') <=> SymbolOperator.new(:foo, 'in')).should == 0
48
46
  end
49
47
 
50
- should "different field" do
48
+ it "returns 1 for different field" do
51
49
  (SymbolOperator.new(:foo, 'in') <=> SymbolOperator.new(:bar, 'in')).should == 1
52
50
  end
53
51
  end
54
52
  end
55
- end
53
+ end
@@ -0,0 +1,9 @@
1
+ require 'helper'
2
+
3
+ describe Symbol do
4
+ SymbolOperators.each do |operator|
5
+ it "responds to #{operator}" do
6
+ :foo.send(operator).should be_instance_of(SymbolOperator)
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plucky
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-12 00:00:00.000000000 Z
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
16
- requirement: &70317435688340 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '1.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70317435688340
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.5'
25
30
  description:
26
31
  email:
27
32
  - nunemaker@gmail.com
@@ -29,9 +34,11 @@ executables: []
29
34
  extensions: []
30
35
  extra_rdoc_files: []
31
36
  files:
37
+ - .bundle/config
32
38
  - .gitignore
33
39
  - .travis.yml
34
40
  - Gemfile
41
+ - Guardfile
35
42
  - LICENSE
36
43
  - README.md
37
44
  - Rakefile
@@ -43,6 +50,13 @@ files:
43
50
  - lib/plucky/extensions/duplicable.rb
44
51
  - lib/plucky/extensions/symbol.rb
45
52
  - lib/plucky/new_relic.rb
53
+ - lib/plucky/normalizers/criteria_hash_key.rb
54
+ - lib/plucky/normalizers/criteria_hash_value.rb
55
+ - lib/plucky/normalizers/fields_value.rb
56
+ - lib/plucky/normalizers/integer.rb
57
+ - lib/plucky/normalizers/options_hash_key.rb
58
+ - lib/plucky/normalizers/options_hash_value.rb
59
+ - lib/plucky/normalizers/sort_value.rb
46
60
  - lib/plucky/options_hash.rb
47
61
  - lib/plucky/pagination.rb
48
62
  - lib/plucky/pagination/decorator.rb
@@ -50,16 +64,24 @@ files:
50
64
  - lib/plucky/query.rb
51
65
  - lib/plucky/version.rb
52
66
  - plucky.gemspec
67
+ - script/criteria_hash.rb
68
+ - spec/helper.rb
69
+ - spec/plucky/criteria_hash_spec.rb
70
+ - spec/plucky/normalizers/criteria_hash_key_spec.rb
71
+ - spec/plucky/normalizers/criteria_hash_value_spec.rb
72
+ - spec/plucky/normalizers/fields_value_spec.rb
73
+ - spec/plucky/normalizers/integer_spec.rb
74
+ - spec/plucky/normalizers/options_hash_key_spec.rb
75
+ - spec/plucky/normalizers/options_hash_value_spec.rb
76
+ - spec/plucky/normalizers/sort_value_spec.rb
77
+ - spec/plucky/options_hash_spec.rb
78
+ - spec/plucky/pagination/decorator_spec.rb
79
+ - spec/plucky/pagination/paginator_spec.rb
80
+ - spec/plucky/query_spec.rb
81
+ - spec/plucky_spec.rb
82
+ - spec/symbol_operator_spec.rb
83
+ - spec/symbol_spec.rb
53
84
  - specs.watchr
54
- - test/helper.rb
55
- - test/plucky/pagination/test_decorator.rb
56
- - test/plucky/pagination/test_paginator.rb
57
- - test/plucky/test_criteria_hash.rb
58
- - test/plucky/test_options_hash.rb
59
- - test/plucky/test_query.rb
60
- - test/test_plucky.rb
61
- - test/test_symbol.rb
62
- - test/test_symbol_operator.rb
63
85
  homepage: http://jnunemaker.github.com/plucky/
64
86
  licenses: []
65
87
  post_install_message:
@@ -72,26 +94,39 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
94
  - - ! '>='
73
95
  - !ruby/object:Gem::Version
74
96
  version: '0'
97
+ segments:
98
+ - 0
99
+ hash: 3663631979890408625
75
100
  required_rubygems_version: !ruby/object:Gem::Requirement
76
101
  none: false
77
102
  requirements:
78
103
  - - ! '>='
79
104
  - !ruby/object:Gem::Version
80
105
  version: '0'
106
+ segments:
107
+ - 0
108
+ hash: 3663631979890408625
81
109
  requirements: []
82
110
  rubyforge_project:
83
- rubygems_version: 1.8.10
111
+ rubygems_version: 1.8.23
84
112
  signing_key:
85
113
  specification_version: 3
86
114
  summary: Thin layer over the ruby driver that allows you to quickly grab hold of your
87
115
  data (pluck it!).
88
116
  test_files:
89
- - test/helper.rb
90
- - test/plucky/pagination/test_decorator.rb
91
- - test/plucky/pagination/test_paginator.rb
92
- - test/plucky/test_criteria_hash.rb
93
- - test/plucky/test_options_hash.rb
94
- - test/plucky/test_query.rb
95
- - test/test_plucky.rb
96
- - test/test_symbol.rb
97
- - test/test_symbol_operator.rb
117
+ - spec/helper.rb
118
+ - spec/plucky/criteria_hash_spec.rb
119
+ - spec/plucky/normalizers/criteria_hash_key_spec.rb
120
+ - spec/plucky/normalizers/criteria_hash_value_spec.rb
121
+ - spec/plucky/normalizers/fields_value_spec.rb
122
+ - spec/plucky/normalizers/integer_spec.rb
123
+ - spec/plucky/normalizers/options_hash_key_spec.rb
124
+ - spec/plucky/normalizers/options_hash_value_spec.rb
125
+ - spec/plucky/normalizers/sort_value_spec.rb
126
+ - spec/plucky/options_hash_spec.rb
127
+ - spec/plucky/pagination/decorator_spec.rb
128
+ - spec/plucky/pagination/paginator_spec.rb
129
+ - spec/plucky/query_spec.rb
130
+ - spec/plucky_spec.rb
131
+ - spec/symbol_operator_spec.rb
132
+ - spec/symbol_spec.rb
@@ -1,120 +0,0 @@
1
- require 'helper'
2
-
3
- class PaginatorTest < Test::Unit::TestCase
4
- include Plucky::Pagination
5
-
6
- context "#initialize" do
7
- context "with total and page" do
8
- setup { @paginator = Paginator.new(20, 2) }
9
- subject { @paginator }
10
-
11
- should "set total" do
12
- subject.total_entries.should == 20
13
- end
14
-
15
- should "set page" do
16
- subject.current_page.should == 2
17
- end
18
-
19
- should "default per_page to 25" do
20
- subject.per_page.should == 25
21
- end
22
- end
23
-
24
- context "with total, page and per_page" do
25
- setup { @paginator = Paginator.new(20, 2, 10) }
26
- subject { @paginator }
27
-
28
- should "set total" do
29
- subject.total_entries.should == 20
30
- end
31
-
32
- should "set page" do
33
- subject.current_page.should == 2
34
- end
35
-
36
- should "set per_page" do
37
- subject.per_page.should == 10
38
- end
39
- end
40
-
41
- context "with string values for total, page and per_page" do
42
- setup { @paginator = Paginator.new('20', '2', '10') }
43
- subject { @paginator }
44
-
45
- should "set total" do
46
- subject.total_entries.should == 20
47
- end
48
-
49
- should "set page" do
50
- subject.current_page.should == 2
51
- end
52
-
53
- should "set per_page" do
54
- subject.per_page.should == 10
55
- end
56
- end
57
-
58
- context "with page less than 1" do
59
- setup { @paginator = Paginator.new(20, -2, 10) }
60
- subject { @paginator }
61
-
62
- should "set page to 1" do
63
- subject.current_page.should == 1
64
- end
65
- end
66
- end
67
-
68
- should "alias limit to per_page" do
69
- Paginator.new(30, 2, 30).limit.should == 30
70
- end
71
-
72
- should "be know total number of pages" do
73
- Paginator.new(43, 2, 7).total_pages.should == 7
74
- Paginator.new(40, 2, 10).total_pages.should == 4
75
- end
76
-
77
- context "#out_of_bounds?" do
78
- should "be true if current_page is greater than total_pages" do
79
- Paginator.new(2, 3, 1).should be_out_of_bounds
80
- end
81
-
82
- should "be false if current page is less than total_pages" do
83
- Paginator.new(2, 1, 1).should_not be_out_of_bounds
84
- end
85
-
86
- should "be false if current page equals total_pages" do
87
- Paginator.new(2, 2, 1).should_not be_out_of_bounds
88
- end
89
- end
90
-
91
- context "#previous_page" do
92
- should "be nil if there is no page less than current" do
93
- Paginator.new(2, 1, 1).previous_page.should be_nil
94
- end
95
-
96
- should "be number less than current page if there is one" do
97
- Paginator.new(2, 2, 1).previous_page.should == 1
98
- end
99
- end
100
-
101
- context "#next_page" do
102
- should "be nil if no page greater than current page" do
103
- Paginator.new(2, 2, 1).next_page.should be_nil
104
- end
105
-
106
- should "be number greater than current page if there is one" do
107
- Paginator.new(2, 1, 1).next_page.should == 2
108
- end
109
- end
110
-
111
- context "#skip" do
112
- should "work" do
113
- Paginator.new(30, 3, 10).skip.should == 20
114
- end
115
-
116
- should "be aliased to offset for will paginate" do
117
- Paginator.new(30, 3, 10).offset.should == 20
118
- end
119
- end
120
- end
@@ -1,359 +0,0 @@
1
- require 'helper'
2
-
3
- class CriteriaHashTest < Test::Unit::TestCase
4
- include Plucky
5
-
6
- context "Plucky::CriteriaHash" do
7
- should "delegate missing methods to the source hash" do
8
- hash = {:baz => 'wick', :foo => 'bar'}
9
- criteria = CriteriaHash.new(hash)
10
- criteria[:foo].should == 'bar'
11
- criteria[:baz].should == 'wick'
12
- criteria.keys.to_set.should == [:baz, :foo].to_set
13
- end
14
-
15
- SymbolOperators.each do |operator|
16
- should "work with #{operator} symbol operator" do
17
- CriteriaHash.new(:age.send(operator) => 21)[:age].should == {"$#{operator}" => 21}
18
- end
19
- end
20
-
21
- should "handle multiple symbol operators on the same field" do
22
- CriteriaHash.new(:age.gt => 12, :age.lt => 20)[:age].should == {
23
- '$gt' => 12, '$lt' => 20
24
- }
25
- end
26
-
27
- context "nested clauses" do
28
- context "::NestingOperators" do
29
- should "return array of operators that take nested queries" do
30
- CriteriaHash::NestingOperators.should == [:$or, :$and, :$nor]
31
- end
32
- end
33
-
34
- CriteriaHash::NestingOperators.each do |operator|
35
- context "#{operator}" do
36
- should "work with symbol operators" do
37
- nested1 = {:age.gt => 12, :age.lt => 20}
38
- translated1 = {:age => {'$gt' => 12, '$lt' => 20 }}
39
- nested2 = {:type.nin => ['friend', 'enemy']}
40
- translated2 = {:type => {'$nin' => ['friend', 'enemy']}}
41
-
42
- given = {operator.to_s => [nested1, nested2]}
43
-
44
- CriteriaHash.new(given)[operator].should == [translated1, translated2]
45
- end
46
-
47
- should "honor criteria hash options" do
48
- nested = {:post_id => '4f5ead6378fca23a13000001'}
49
- translated = {:post_id => BSON::ObjectId.from_string('4f5ead6378fca23a13000001')}
50
- given = {operator.to_s => [nested]}
51
-
52
- CriteriaHash.new(given, :object_ids => [:post_id])[operator].should == [translated]
53
- end
54
- end
55
- end
56
-
57
- context "doubly nested" do
58
- should "work with symbol operators" do
59
- nested1 = {:age.gt => 12, :age.lt => 20}
60
- translated1 = {:age => {'$gt' => 12, '$lt' => 20}}
61
- nested2 = {:type.nin => ['friend', 'enemy']}
62
- translated2 = {:type => {'$nin' => ['friend', 'enemy']}}
63
- nested3 = {'$and' => [nested2]}
64
- translated3 = {:$and => [translated2]}
65
-
66
- given = {'$or' => [nested1, nested3]}
67
-
68
- CriteriaHash.new(given)[:$or].should == [translated1, translated3]
69
- end
70
- end
71
- end
72
-
73
- context "#initialize_copy" do
74
- setup do
75
- @original = CriteriaHash.new({
76
- :comments => {:_id => 1}, :tags => ['mongo', 'ruby'],
77
- }, :object_ids => [:_id])
78
- @cloned = @original.clone
79
- end
80
-
81
- should "duplicate source hash" do
82
- @cloned.source.should_not equal(@original.source)
83
- end
84
-
85
- should "duplicate options hash" do
86
- @cloned.options.should_not equal(@original.options)
87
- end
88
-
89
- should "clone duplicable? values" do
90
- @cloned[:comments].should_not equal(@original[:comments])
91
- @cloned[:tags].should_not equal(@original[:tags])
92
- end
93
- end
94
-
95
- context "#object_ids=" do
96
- should "work with array" do
97
- criteria = CriteriaHash.new
98
- criteria.object_ids = [:_id]
99
- criteria.object_ids.should == [:_id]
100
- end
101
-
102
- should "flatten multi-dimensional array" do
103
- criteria = CriteriaHash.new
104
- criteria.object_ids = [[:_id]]
105
- criteria.object_ids.should == [:_id]
106
- end
107
-
108
- should "raise argument error if not array" do
109
- assert_raises(ArgumentError) { CriteriaHash.new.object_ids = {} }
110
- assert_raises(ArgumentError) { CriteriaHash.new.object_ids = nil }
111
- assert_raises(ArgumentError) { CriteriaHash.new.object_ids = 'foo' }
112
- end
113
- end
114
-
115
- context "#[]=" do
116
- should "leave string values for string keys alone" do
117
- criteria = CriteriaHash.new
118
- criteria[:foo] = 'bar'
119
- criteria[:foo].should == 'bar'
120
- end
121
-
122
- should "convert string values to object ids for object id keys" do
123
- id = BSON::ObjectId.new
124
- criteria = CriteriaHash.new({}, :object_ids => [:_id])
125
- criteria[:_id] = id.to_s
126
- criteria[:_id].should == id
127
- end
128
-
129
- should "convert sets to arrays" do
130
- criteria = CriteriaHash.new
131
- criteria[:foo] = [1, 2].to_set
132
- criteria[:foo].should == {'$in' => [1, 2]}
133
- end
134
-
135
- should "convert times to utc" do
136
- time = Time.now
137
- criteria = CriteriaHash.new
138
- criteria[:foo] = time
139
- criteria[:foo].should be_utc
140
- criteria[:foo].should == time.utc
141
- end
142
-
143
- should "convert :id to :_id" do
144
- criteria = CriteriaHash.new
145
- criteria[:id] = 1
146
- criteria[:_id].should == 1
147
- criteria[:id].should be_nil
148
- end
149
-
150
- should "work with symbol operators" do
151
- criteria = CriteriaHash.new
152
- criteria[:_id.in] = ['foo']
153
- criteria[:_id].should == {'$in' => ['foo']}
154
- end
155
-
156
- should "set each of the conditions pairs" do
157
- criteria = CriteriaHash.new
158
- criteria[:conditions] = {:_id => 'john', :foo => 'bar'}
159
- criteria[:_id].should == 'john'
160
- criteria[:foo].should == 'bar'
161
- end
162
- end
163
-
164
- context "with id key" do
165
- should "convert to _id" do
166
- id = BSON::ObjectId.new
167
- criteria = CriteriaHash.new(:id => id)
168
- criteria[:_id].should == id
169
- criteria[:id].should be_nil
170
- end
171
-
172
- should "convert id with symbol operator to _id with modifier" do
173
- id = BSON::ObjectId.new
174
- criteria = CriteriaHash.new(:id.ne => id)
175
- criteria[:_id].should == {'$ne' => id}
176
- criteria[:id].should be_nil
177
- end
178
- end
179
-
180
- context "with time value" do
181
- should "convert to utc if not utc" do
182
- CriteriaHash.new(:created_at => Time.now)[:created_at].utc?.should be(true)
183
- end
184
-
185
- should "leave utc alone" do
186
- CriteriaHash.new(:created_at => Time.now.utc)[:created_at].utc?.should be(true)
187
- end
188
- end
189
-
190
- context "with array value" do
191
- should "default to $in" do
192
- CriteriaHash.new(:numbers => [1,2,3])[:numbers].should == {'$in' => [1,2,3]}
193
- end
194
-
195
- should "use existing modifier if present" do
196
- CriteriaHash.new(:numbers => {'$all' => [1,2,3]})[:numbers].should == {'$all' => [1,2,3]}
197
- CriteriaHash.new(:numbers => {'$any' => [1,2,3]})[:numbers].should == {'$any' => [1,2,3]}
198
- end
199
-
200
- should "not turn value to $in with $or key" do
201
- CriteriaHash.new(:$or => [{:numbers => 1}, {:numbers => 2}] )[:$or].should == [{:numbers=>1}, {:numbers=>2}]
202
- end
203
-
204
- should "not turn value to $in with $and key" do
205
- CriteriaHash.new(:$and => [{:numbers => 1}, {:numbers => 2}] )[:$and].should == [{:numbers=>1}, {:numbers=>2}]
206
- end
207
-
208
- should "not turn value to $in with $nor key" do
209
- CriteriaHash.new(:$nor => [{:numbers => 1}, {:numbers => 2}] )[:$nor].should == [{:numbers=>1}, {:numbers=>2}]
210
- end
211
-
212
- should "default to $in even with ObjectId keys" do
213
- CriteriaHash.new({:mistake_id => [1,2,3]}, :object_ids => [:mistake_id])[:mistake_id].should == {'$in' => [1,2,3]}
214
- end
215
- end
216
-
217
- context "with set value" do
218
- should "default to $in and convert to array" do
219
- CriteriaHash.new(:numbers => [1,2,3].to_set)[:numbers].should == {'$in' => [1,2,3]}
220
- end
221
-
222
- should "use existing modifier if present and convert to array" do
223
- CriteriaHash.new(:numbers => {'$all' => [1,2,3].to_set})[:numbers].should == {'$all' => [1,2,3]}
224
- CriteriaHash.new(:numbers => {'$any' => [1,2,3].to_set})[:numbers].should == {'$any' => [1,2,3]}
225
- end
226
- end
227
-
228
- context "with string ids for string keys" do
229
- setup do
230
- @id = BSON::ObjectId.new
231
- @room_id = BSON::ObjectId.new
232
- @criteria = CriteriaHash.new(:_id => @id.to_s, :room_id => @room_id.to_s)
233
- end
234
-
235
- should "leave string ids as strings" do
236
- @criteria[:_id].should == @id.to_s
237
- @criteria[:room_id].should == @room_id.to_s
238
- @criteria[:_id].should be_instance_of(String)
239
- @criteria[:room_id].should be_instance_of(String)
240
- end
241
- end
242
-
243
- context "with string ids for object id keys" do
244
- setup do
245
- @id = BSON::ObjectId.new
246
- @room_id = BSON::ObjectId.new
247
- end
248
-
249
- should "convert strings to object ids" do
250
- criteria = CriteriaHash.new({:_id => @id.to_s, :room_id => @room_id.to_s}, :object_ids => [:_id, :room_id])
251
- criteria[:_id].should == @id
252
- criteria[:room_id].should == @room_id
253
- criteria[:_id].should be_instance_of(BSON::ObjectId)
254
- criteria[:room_id].should be_instance_of(BSON::ObjectId)
255
- end
256
-
257
- should "convert :id with string value to object id value" do
258
- criteria = CriteriaHash.new({:id => @id.to_s}, :object_ids => [:_id])
259
- criteria[:_id].should == @id
260
- end
261
- end
262
-
263
- context "with string ids for object id keys (nested)" do
264
- setup do
265
- @id1 = BSON::ObjectId.new
266
- @id2 = BSON::ObjectId.new
267
- @ids = [@id1.to_s, @id2.to_s]
268
- @criteria = CriteriaHash.new({:_id => {'$in' => @ids}}, :object_ids => [:_id])
269
- end
270
-
271
- should "convert strings to object ids" do
272
- @criteria[:_id].should == {'$in' => [@id1, @id2]}
273
- end
274
-
275
- should "not modify original array of string ids" do
276
- @ids.should == [@id1.to_s, @id2.to_s]
277
- end
278
- end
279
-
280
- context "#merge" do
281
- should "work when no keys match" do
282
- c1 = CriteriaHash.new(:foo => 'bar')
283
- c2 = CriteriaHash.new(:baz => 'wick')
284
- c1.merge(c2).should == CriteriaHash.new(:foo => 'bar', :baz => 'wick')
285
- end
286
-
287
- should "turn matching keys with simple values into array" do
288
- c1 = CriteriaHash.new(:foo => 'bar')
289
- c2 = CriteriaHash.new(:foo => 'baz')
290
- c1.merge(c2).should == CriteriaHash.new(:foo => {'$in' => %w[bar baz]})
291
- end
292
-
293
- should "unique matching key values" do
294
- c1 = CriteriaHash.new(:foo => 'bar')
295
- c2 = CriteriaHash.new(:foo => 'bar')
296
- c1.merge(c2).should == CriteriaHash.new(:foo => {'$in' => %w[bar]})
297
- end
298
-
299
- should "correctly merge arrays and non-arrays" do
300
- c1 = CriteriaHash.new(:foo => 'bar')
301
- c2 = CriteriaHash.new(:foo => %w[bar baz])
302
- c1.merge(c2).should == CriteriaHash.new(:foo => {'$in' => %w[bar baz]})
303
- c2.merge(c1).should == CriteriaHash.new(:foo => {'$in' => %w[bar baz]})
304
- end
305
-
306
- should "be able to merge two modifier hashes" do
307
- c1 = CriteriaHash.new('$in' => [1, 2])
308
- c2 = CriteriaHash.new('$in' => [2, 3])
309
- c1.merge(c2).should == CriteriaHash.new('$in' => [1, 2, 3])
310
- end
311
-
312
- should "merge matching keys with a single modifier" do
313
- c1 = CriteriaHash.new(:foo => {'$in' => [1, 2, 3]})
314
- c2 = CriteriaHash.new(:foo => {'$in' => [1, 4, 5]})
315
- c1.merge(c2).should == CriteriaHash.new(:foo => {'$in' => [1, 2, 3, 4, 5]})
316
- end
317
-
318
- should "merge matching keys with multiple modifiers" do
319
- c1 = CriteriaHash.new(:foo => {'$in' => [1, 2, 3]})
320
- c2 = CriteriaHash.new(:foo => {'$all' => [1, 4, 5]})
321
- c1.merge(c2).should == CriteriaHash.new(:foo => {'$in' => [1, 2, 3], '$all' => [1, 4, 5]})
322
- end
323
-
324
- should "not update mergee" do
325
- c1 = CriteriaHash.new(:foo => 'bar')
326
- c2 = CriteriaHash.new(:foo => 'baz')
327
- c1.merge(c2).should_not equal(c1)
328
- c1[:foo].should == 'bar'
329
- end
330
- end
331
-
332
- context "#merge!" do
333
- should "merge and replace" do
334
- c1 = CriteriaHash.new(:foo => 'bar')
335
- c2 = CriteriaHash.new(:foo => 'baz')
336
- c1.merge!(c2)
337
- c1[:foo].should == {'$in' => ['bar', 'baz']}
338
- end
339
- end
340
-
341
- context "#simple?" do
342
- should "be true if only filtering by _id" do
343
- CriteriaHash.new(:_id => 'id').should be_simple
344
- end
345
-
346
- should "be true if only filtering by Sci" do
347
- CriteriaHash.new(:_id => 'id', :_type => 'Foo').should be_simple
348
- end
349
-
350
- should "be false if querying by anthing other than _id/Sci" do
351
- CriteriaHash.new(:foo => 'bar').should_not be_simple
352
- end
353
-
354
- should "be false if querying only by _type" do
355
- CriteriaHash.new(:_type => 'Foo').should_not be_simple
356
- end
357
- end
358
- end
359
- end