plucky 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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