plucky 0.6.3 → 0.8.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -3
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -4
- data/Gemfile +6 -5
- data/Gemfile.lock +84 -0
- data/LICENSE +1 -1
- data/README.md +17 -75
- data/Rakefile +0 -3
- data/examples/query.rb +8 -7
- data/lib/plucky.rb +1 -0
- data/lib/plucky/criteria_hash.rb +78 -62
- data/lib/plucky/extensions/symbol.rb +8 -0
- data/lib/plucky/normalizers/criteria_hash_value.rb +3 -1
- data/lib/plucky/normalizers/fields_value.rb +3 -3
- data/lib/plucky/normalizers/hash_key.rb +19 -0
- data/lib/plucky/normalizers/options_hash_value.rb +5 -7
- data/lib/plucky/normalizers/sort_value.rb +8 -6
- data/lib/plucky/options_hash.rb +9 -3
- data/lib/plucky/pagination.rb +1 -1
- data/lib/plucky/pagination/{decorator.rb → collection.rb} +10 -1
- data/lib/plucky/query.rb +56 -21
- data/lib/plucky/transformer.rb +14 -0
- data/lib/plucky/version.rb +1 -1
- data/plucky.gemspec +4 -5
- data/script/bootstrap +21 -0
- data/script/release +42 -0
- data/script/test +20 -0
- data/spec/functional/options_hash_spec.rb +41 -0
- data/spec/helper.rb +12 -4
- data/spec/plucky/criteria_hash_spec.rb +68 -4
- data/spec/plucky/normalizers/criteria_hash_value_spec.rb +1 -1
- data/spec/plucky/normalizers/fields_value_spec.rb +5 -5
- data/spec/plucky/normalizers/hash_key_spec.rb +15 -0
- data/spec/plucky/normalizers/options_hash_value_spec.rb +2 -2
- data/spec/plucky/normalizers/sort_value_spec.rb +24 -20
- data/spec/plucky/options_hash_spec.rb +2 -2
- data/spec/plucky/pagination/{decorator_spec.rb → collection_spec.rb} +8 -5
- data/spec/plucky/query_spec.rb +92 -35
- data/spec/plucky_spec.rb +5 -5
- data/spec/symbol_operator_spec.rb +18 -1
- metadata +37 -36
- data/lib/plucky/normalizers/options_hash_key.rb +0 -23
- data/script/criteria_hash.rb +0 -21
- data/spec/plucky/normalizers/options_hash_key_spec.rb +0 -23
data/script/test
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#/ Usage: test
|
3
|
+
#/
|
4
|
+
#/ Bootstrap and run all tests.
|
5
|
+
#/
|
6
|
+
#/ Examples:
|
7
|
+
#/
|
8
|
+
#/ # run all tests
|
9
|
+
#/ test
|
10
|
+
#/
|
11
|
+
|
12
|
+
set -e
|
13
|
+
cd $(dirname "$0")/..
|
14
|
+
|
15
|
+
[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
|
16
|
+
grep '^#/' <"$0"| cut -c4-
|
17
|
+
exit 0
|
18
|
+
}
|
19
|
+
|
20
|
+
script/bootstrap && bundle exec rake
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Plucky::OptionsHash do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
describe "#[]=" do
|
7
|
+
it "changes order to sort" do
|
8
|
+
subject[:order] = "foo asc"
|
9
|
+
subject[:sort].should == {"foo" => 1}
|
10
|
+
subject[:order].should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "changes sort(id) to sort(_id)" do
|
14
|
+
subject[:sort] = "id asc"
|
15
|
+
subject[:sort].should == {"_id" => 1}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "changes select to fields" do
|
19
|
+
subject[:select] = [:foo]
|
20
|
+
subject[:projection].should == {:foo => 1}
|
21
|
+
subject[:select].should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "changes offset to skip" do
|
25
|
+
subject[:offset] = 10
|
26
|
+
subject[:skip].should == 10
|
27
|
+
subject[:offset].should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "changes id to _id" do
|
31
|
+
subject[:id] = :foo
|
32
|
+
subject[:_id].should == :foo
|
33
|
+
subject[:id].should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it "does not change the sort field" do
|
37
|
+
subject[:order] = :order.asc
|
38
|
+
subject[:sort].should == {"order" => 1}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/helper.rb
CHANGED
@@ -11,14 +11,19 @@ require 'fileutils'
|
|
11
11
|
require 'logger'
|
12
12
|
require 'pp'
|
13
13
|
|
14
|
+
if RUBY_ENGINE == "ruby" && RUBY_VERSION >= '2.3'
|
15
|
+
require 'byebug'
|
16
|
+
end
|
17
|
+
|
14
18
|
log_dir = File.expand_path('../../log', __FILE__)
|
15
19
|
FileUtils.mkdir_p(log_dir)
|
16
20
|
Log = Logger.new(File.join(log_dir, 'test.log'))
|
17
21
|
|
18
22
|
LogBuddy.init :logger => Log
|
19
23
|
|
20
|
-
|
21
|
-
|
24
|
+
port = ENV.fetch "BOXEN_MONGODB_PORT", 27017
|
25
|
+
connection = Mongo::Client.new(["127.0.0.1:#{port.to_i}"], :logger => Log)
|
26
|
+
DB = connection.use('test').database
|
22
27
|
|
23
28
|
RSpec.configure do |config|
|
24
29
|
config.filter_run :focused => true
|
@@ -26,16 +31,19 @@ RSpec.configure do |config|
|
|
26
31
|
config.alias_example_to :xit, :pending => true
|
27
32
|
config.run_all_when_everything_filtered = true
|
28
33
|
|
34
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
35
|
+
config.mock_with(:rspec) { |c| c.syntax = :should }
|
36
|
+
|
29
37
|
config.before(:suite) do
|
30
38
|
DB.collections.reject { |collection|
|
31
39
|
collection.name =~ /system\./
|
32
|
-
}.
|
40
|
+
}.each { |collection| collection.indexes.drop_all}
|
33
41
|
end
|
34
42
|
|
35
43
|
config.before(:each) do
|
36
44
|
DB.collections.reject { |collection|
|
37
45
|
collection.name =~ /system\./
|
38
|
-
}.map(&:
|
46
|
+
}.map(&:drop)
|
39
47
|
end
|
40
48
|
end
|
41
49
|
|
@@ -37,9 +37,9 @@ describe Plucky::CriteriaHash do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "raises argument error if not array" do
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
lambda { described_class.new.object_ids = {} }.should raise_error(ArgumentError)
|
41
|
+
lambda { described_class.new.object_ids = nil }.should raise_error(ArgumentError)
|
42
|
+
lambda { described_class.new.object_ids = 'foo' }.should raise_error(ArgumentError)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -90,7 +90,7 @@ describe Plucky::CriteriaHash do
|
|
90
90
|
it "uniques matching key values" do
|
91
91
|
c1 = described_class.new(:foo => 'bar')
|
92
92
|
c2 = described_class.new(:foo => 'bar')
|
93
|
-
c1.merge(c2).source.should eq(:foo =>
|
93
|
+
c1.merge(c2).source.should eq(:foo => 'bar')
|
94
94
|
end
|
95
95
|
|
96
96
|
it "correctly merges arrays and non-arrays" do
|
@@ -147,6 +147,70 @@ describe Plucky::CriteriaHash do
|
|
147
147
|
c1.merge(c2).should_not equal(c1)
|
148
148
|
c1[:foo].should == 'bar'
|
149
149
|
end
|
150
|
+
|
151
|
+
it "merges two hashes with the same key, but nil values as nil" do
|
152
|
+
c1 = described_class.new(:foo => nil)
|
153
|
+
c2 = described_class.new(:foo => nil)
|
154
|
+
c1.merge(c2).source.should == { :foo => nil }
|
155
|
+
end
|
156
|
+
|
157
|
+
it "merges two hashes with the same key, but false values as false" do
|
158
|
+
c1 = described_class.new(:foo => false)
|
159
|
+
c2 = described_class.new(:foo => false)
|
160
|
+
c1.merge(c2).source.should == { :foo => false }
|
161
|
+
end
|
162
|
+
|
163
|
+
it "merges two hashes with the same key, but different values with $in" do
|
164
|
+
c1 = described_class.new(:foo => false)
|
165
|
+
c2 = described_class.new(:foo => true)
|
166
|
+
c1.merge(c2).source.should == { :foo => { :'$in' => [false, true] } }
|
167
|
+
end
|
168
|
+
|
169
|
+
it "merges two hashes with different keys and different values properly" do
|
170
|
+
c1 = described_class.new(:foo => 1)
|
171
|
+
c2 = described_class.new(:bar => 2)
|
172
|
+
c1.merge(c2).source.should == { :foo => 1, :bar => 2 }
|
173
|
+
end
|
174
|
+
|
175
|
+
it "merges two sets" do
|
176
|
+
c1 = described_class.new(:foo => Set.new([1, 2]))
|
177
|
+
c2 = described_class.new(:foo => Set.new([2, 3]))
|
178
|
+
c1.merge(c2).source.should == { :foo => { :'$in' => [1,2,3] } }
|
179
|
+
end
|
180
|
+
|
181
|
+
context "given multiple $or clauses" do
|
182
|
+
before do
|
183
|
+
@c1 = described_class.new(:$or => [{:a => 1}, {:b => 2}])
|
184
|
+
@c2 = described_class.new(:$or => [{:a => 3}, {:b => 4}])
|
185
|
+
@c3 = described_class.new(:$or => [{:a => 4}, {:b => 4}])
|
186
|
+
end
|
187
|
+
|
188
|
+
it "merges two $ors into a compound $and" do
|
189
|
+
merged = @c1.merge(@c2)
|
190
|
+
merged[:$and].should == [
|
191
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
192
|
+
{:$or => [{:a => 3}, {:b => 4}]}
|
193
|
+
]
|
194
|
+
end
|
195
|
+
|
196
|
+
it "merges an $and and a $or into a compound $and" do
|
197
|
+
merged = @c1.merge(@c2).merge(@c3)
|
198
|
+
merged[:$and].should == [
|
199
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
200
|
+
{:$or => [{:a => 3}, {:b => 4}]},
|
201
|
+
{:$or => [{:a => 4}, {:b => 4}]}
|
202
|
+
]
|
203
|
+
end
|
204
|
+
|
205
|
+
it "merges an $or and an $and into a compound $and" do
|
206
|
+
merged = @c3.merge @c1.merge(@c2)
|
207
|
+
merged[:$and].should == [
|
208
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
209
|
+
{:$or => [{:a => 3}, {:b => 4}]},
|
210
|
+
{:$or => [{:a => 4}, {:b => 4}]}
|
211
|
+
]
|
212
|
+
end
|
213
|
+
end
|
150
214
|
end
|
151
215
|
|
152
216
|
context "#merge!" do
|
@@ -155,7 +155,7 @@ describe Plucky::Normalizers::CriteriaHashValue do
|
|
155
155
|
|
156
156
|
context "nested clauses" do
|
157
157
|
it "knows constant array of operators that take nested queries" do
|
158
|
-
described_class::NestingOperators.should == [:$or, :$and, :$nor]
|
158
|
+
described_class::NestingOperators.should == Set[:$or, :$and, :$nor]
|
159
159
|
end
|
160
160
|
|
161
161
|
described_class::NestingOperators.each do |operator|
|
@@ -15,7 +15,7 @@ describe Plucky::Normalizers::FieldsValue do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it "works with array" do
|
18
|
-
subject.call(['one', 'two']).should eq(
|
18
|
+
subject.call(['one', 'two']).should eq({'one' => 1, 'two' => 1})
|
19
19
|
end
|
20
20
|
|
21
21
|
# Ruby 1.9.x was sending array [{:age => 20}], instead of hash.
|
@@ -24,15 +24,15 @@ describe Plucky::Normalizers::FieldsValue do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "flattens multi-dimensional array" do
|
27
|
-
subject.call([[:one, :two]]).should eq(
|
27
|
+
subject.call([[:one, :two]]).should eq({:one => 1, :two => 1})
|
28
28
|
end
|
29
29
|
|
30
30
|
it "works with symbol" do
|
31
|
-
subject.call(:one).should eq(
|
31
|
+
subject.call(:one).should eq({:one => 1})
|
32
32
|
end
|
33
33
|
|
34
34
|
it "works with array of symbols" do
|
35
|
-
subject.call([:one, :two]).should eq(
|
35
|
+
subject.call([:one, :two]).should eq({:one => 1, :two => 1})
|
36
36
|
end
|
37
37
|
|
38
38
|
it "works with hash" do
|
@@ -40,6 +40,6 @@ describe Plucky::Normalizers::FieldsValue do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "converts comma separated list to array" do
|
43
|
-
subject.call('one, two').should eq(
|
43
|
+
subject.call('one, two').should eq({'one' => 1, 'two' => 1})
|
44
44
|
end
|
45
45
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Plucky::Normalizers::HashKey do
|
4
|
+
subject {
|
5
|
+
described_class.new(:bacon => :sizzle)
|
6
|
+
}
|
7
|
+
|
8
|
+
it "changes defined fields" do
|
9
|
+
subject.call(:bacon).should eq(:sizzle)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "does not change undefined fields" do
|
13
|
+
subject.call(:sausage).should eq(:sausage)
|
14
|
+
end
|
15
|
+
end
|
@@ -26,9 +26,9 @@ describe Plucky::Normalizers::OptionsHashValue do
|
|
26
26
|
}
|
27
27
|
|
28
28
|
it "raises exception if missing key normalizer" do
|
29
|
-
|
29
|
+
lambda {
|
30
30
|
described_class.new
|
31
|
-
}.
|
31
|
+
}.should raise_error(ArgumentError, "Missing required key :key_normalizer")
|
32
32
|
end
|
33
33
|
|
34
34
|
it "allows injecting a new value normalizer" do
|
@@ -3,7 +3,7 @@ require 'plucky/normalizers/sort_value'
|
|
3
3
|
|
4
4
|
describe Plucky::Normalizers::SortValue do
|
5
5
|
let(:key_normalizer) {
|
6
|
-
|
6
|
+
Plucky::Normalizers::HashKey.new({:id => :_id})
|
7
7
|
}
|
8
8
|
|
9
9
|
subject {
|
@@ -13,9 +13,9 @@ describe Plucky::Normalizers::SortValue do
|
|
13
13
|
}
|
14
14
|
|
15
15
|
it "raises exception if missing key normalizer" do
|
16
|
-
|
16
|
+
lambda {
|
17
17
|
described_class.new
|
18
|
-
}.
|
18
|
+
}.should raise_error(ArgumentError, "Missing required key :key_normalizer")
|
19
19
|
end
|
20
20
|
|
21
21
|
it "defaults to nil" do
|
@@ -31,64 +31,68 @@ describe Plucky::Normalizers::SortValue do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "converts single ascending field (string)" do
|
34
|
-
subject.call('foo asc').should eq(
|
35
|
-
subject.call('foo ASC').should eq(
|
34
|
+
subject.call('foo asc').should eq({'foo' => 1})
|
35
|
+
subject.call('foo ASC').should eq({'foo' => 1})
|
36
36
|
end
|
37
37
|
|
38
38
|
it "converts single descending field (string)" do
|
39
|
-
subject.call('foo desc').should eq(
|
40
|
-
subject.call('foo DESC').should eq(
|
39
|
+
subject.call('foo desc').should eq({'foo' => -1})
|
40
|
+
subject.call('foo DESC').should eq({'foo' => -1})
|
41
41
|
end
|
42
42
|
|
43
43
|
it "converts multiple fields (string)" do
|
44
|
-
subject.call('foo desc, bar asc').should eq(
|
44
|
+
subject.call('foo desc, bar asc').should eq({'foo' => -1, 'bar' => 1})
|
45
45
|
end
|
46
46
|
|
47
47
|
it "converts multiple fields and default no direction to ascending (string)" do
|
48
|
-
subject.call('foo desc, bar, baz').should eq(
|
48
|
+
subject.call('foo desc, bar, baz').should eq({'foo' => -1, 'bar' => 1, 'baz' => 1})
|
49
49
|
end
|
50
50
|
|
51
51
|
it "converts symbol" do
|
52
|
-
subject.call(:name).should eq(
|
52
|
+
subject.call(:name).should eq({'name' => 1})
|
53
53
|
end
|
54
54
|
|
55
55
|
it "converts operator" do
|
56
|
-
subject.call(:foo.desc).should eq(
|
56
|
+
subject.call(:foo.desc).should eq({'foo' => -1})
|
57
57
|
end
|
58
58
|
|
59
59
|
it "converts array of operators" do
|
60
|
-
subject.call([:foo.desc, :bar.asc]).should eq(
|
60
|
+
subject.call([:foo.desc, :bar.asc]).should eq({'foo' => -1, 'bar' => 1})
|
61
61
|
end
|
62
62
|
|
63
63
|
it "converts array of symbols" do
|
64
|
-
subject.call([:first_name, :last_name]).should eq(
|
64
|
+
subject.call([:first_name, :last_name]).should eq({'first_name' => 1, 'last_name' => 1})
|
65
65
|
end
|
66
66
|
|
67
67
|
it "works with array and one string element" do
|
68
|
-
subject.call(['foo, bar desc']).should eq(
|
68
|
+
subject.call(['foo, bar desc']).should eq({'foo' => 1, 'bar' => -1})
|
69
69
|
end
|
70
70
|
|
71
71
|
it "works with array of single array" do
|
72
|
-
subject.call([['foo', -1]]).should eq(
|
72
|
+
subject.call([['foo', -1]]).should eq({'foo' => -1})
|
73
73
|
end
|
74
74
|
|
75
75
|
it "works with array of multiple arrays" do
|
76
|
-
subject.call([['foo', -1], ['bar', 1]]).should eq(
|
76
|
+
subject.call([['foo', -1], ['bar', 1]]).should eq({'foo' => -1, 'bar' => 1})
|
77
77
|
end
|
78
78
|
|
79
79
|
it "compacts nil values in array" do
|
80
|
-
subject.call([nil, :foo.desc]).should eq(
|
80
|
+
subject.call([nil, :foo.desc]).should eq({'foo' => -1})
|
81
81
|
end
|
82
82
|
|
83
83
|
it "converts array with mix of values" do
|
84
|
-
subject.call([:foo.desc, 'bar']).should eq(
|
84
|
+
subject.call([:foo.desc, 'bar']).should eq({'foo' => -1, 'bar' => 1})
|
85
85
|
end
|
86
86
|
|
87
87
|
it "converts keys based on key normalizer" do
|
88
|
-
subject.call([:id.asc]).should eq(
|
88
|
+
subject.call([:id.asc]).should eq({'_id' => 1})
|
89
|
+
end
|
90
|
+
|
91
|
+
it "doesn't convert keys like :sort to :order via key normalizer" do
|
92
|
+
subject.call(:order.asc).should eq({'order' => 1})
|
89
93
|
end
|
90
94
|
|
91
95
|
it "converts string with $natural correctly" do
|
92
|
-
subject.call('$natural desc').should eq(
|
96
|
+
subject.call('$natural desc').should eq({'$natural' => -1})
|
93
97
|
end
|
94
98
|
end
|
@@ -3,7 +3,7 @@ require 'helper'
|
|
3
3
|
describe Plucky::OptionsHash do
|
4
4
|
describe "#initialize_copy" do
|
5
5
|
before do
|
6
|
-
@original = described_class.new(:
|
6
|
+
@original = described_class.new(:projection => {:name => true}, :sort => :name, :limit => 10)
|
7
7
|
@cloned = @original.clone
|
8
8
|
end
|
9
9
|
|
@@ -12,7 +12,7 @@ describe Plucky::OptionsHash do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "clones duplicable? values" do
|
15
|
-
@cloned[:
|
15
|
+
@cloned[:projection].should_not equal(@original[:projection])
|
16
16
|
@cloned[:sort].should_not equal(@original[:sort])
|
17
17
|
end
|
18
18
|
end
|
@@ -1,15 +1,13 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
describe Plucky::Pagination::
|
4
|
-
context "Object decorated with
|
3
|
+
describe Plucky::Pagination::Collection do
|
4
|
+
context "Object decorated with Collection with paginator set" do
|
5
5
|
before do
|
6
6
|
@object = [1, 2, 3, 4]
|
7
7
|
@object_id = @object.object_id
|
8
8
|
@paginator = Plucky::Pagination::Paginator.new(20, 2, 10)
|
9
|
-
@object.extend(described_class)
|
10
|
-
@object.paginator(@paginator)
|
11
9
|
end
|
12
|
-
subject { @object }
|
10
|
+
subject { Plucky::Pagination::Collection.new(@object, @paginator) }
|
13
11
|
|
14
12
|
it "knows paginator" do
|
15
13
|
subject.paginator.should == @paginator
|
@@ -28,5 +26,10 @@ describe Plucky::Pagination::Decorator do
|
|
28
26
|
@object.size.should == 4
|
29
27
|
@object.select { |o| o > 2 }.should == [3, 4]
|
30
28
|
end
|
29
|
+
|
30
|
+
it "delegates missing methods to the paginator" do
|
31
|
+
@paginator.should_receive(:blather_matter).with('hello', :xyz, 4)
|
32
|
+
subject.blather_matter('hello', :xyz, 4)
|
33
|
+
end
|
31
34
|
end
|
32
35
|
end
|
data/spec/plucky/query_spec.rb
CHANGED
@@ -2,13 +2,13 @@ require 'helper'
|
|
2
2
|
|
3
3
|
describe Plucky::Query do
|
4
4
|
before do
|
5
|
-
@chris =
|
6
|
-
@steve =
|
7
|
-
@john =
|
5
|
+
@chris = Hash['_id', 'chris', 'age', 26, 'name', 'Chris']
|
6
|
+
@steve = Hash['_id', 'steve', 'age', 29, 'name', 'Steve']
|
7
|
+
@john = Hash['_id', 'john', 'age', 28, 'name', 'John']
|
8
8
|
@collection = DB['users']
|
9
|
-
@collection.
|
10
|
-
@collection.
|
11
|
-
@collection.
|
9
|
+
@collection.insert_one(@chris)
|
10
|
+
@collection.insert_one(@steve)
|
11
|
+
@collection.insert_one(@john)
|
12
12
|
end
|
13
13
|
|
14
14
|
context "#initialize" do
|
@@ -57,7 +57,7 @@ describe Plucky::Query do
|
|
57
57
|
context "#find_each" do
|
58
58
|
it "returns a cursor" do
|
59
59
|
cursor = described_class.new(@collection).find_each
|
60
|
-
cursor.should be_instance_of(
|
60
|
+
cursor.should be_instance_of(Enumerator)
|
61
61
|
end
|
62
62
|
|
63
63
|
it "works with and normalize criteria" do
|
@@ -78,8 +78,8 @@ describe Plucky::Query do
|
|
78
78
|
|
79
79
|
it "is Ruby-like and returns a reset cursor if a block is given" do
|
80
80
|
cursor = described_class.new(@collection).find_each {}
|
81
|
-
cursor.should be_instance_of(
|
82
|
-
cursor.next.should
|
81
|
+
cursor.should be_instance_of(Enumerator)
|
82
|
+
cursor.next.should be_kind_of(Hash)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -128,7 +128,7 @@ describe Plucky::Query do
|
|
128
128
|
end
|
129
129
|
|
130
130
|
it "normalizes if using object id" do
|
131
|
-
id = @collection.
|
131
|
+
id = @collection.insert_one(:name => 'Frank').inserted_id
|
132
132
|
@query.object_ids([:_id])
|
133
133
|
doc = @query.find(id.to_s)
|
134
134
|
doc['name'].should == 'Frank'
|
@@ -203,6 +203,27 @@ describe Plucky::Query do
|
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
206
|
+
context "#view" do
|
207
|
+
it 'returns a mongo::collection::view' do
|
208
|
+
described_class.new(@collection).view.should be_a(Mongo::Collection::View)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'converts criteria into the view' do
|
212
|
+
view = described_class.new(@collection).where(:name => "bob").view
|
213
|
+
view.filter.should == {"name" => "bob"}
|
214
|
+
end
|
215
|
+
|
216
|
+
it "converts read option symbol to a server selector" do
|
217
|
+
view = described_class.new(@collection, :read => :secondary_preferred).view
|
218
|
+
view.read.should be_a(Mongo::ServerSelector::SecondaryPreferred)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "converts read option hash to a server selector" do
|
222
|
+
view = described_class.new(@collection, :read => {:mode =>:secondary_preferred}).view
|
223
|
+
view.read.should be_a(Mongo::ServerSelector::SecondaryPreferred)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
206
227
|
context "#all" do
|
207
228
|
it "works with no arguments" do
|
208
229
|
docs = described_class.new(@collection).all
|
@@ -279,6 +300,10 @@ describe Plucky::Query do
|
|
279
300
|
query.count(:name => 'Steve')
|
280
301
|
query[:name].should be_nil
|
281
302
|
end
|
303
|
+
|
304
|
+
it 'counts the result set and not the enumerator' do
|
305
|
+
described_class.new(@collection).limit(1).count.should == 3
|
306
|
+
end
|
282
307
|
end
|
283
308
|
|
284
309
|
context "#size" do
|
@@ -290,8 +315,8 @@ describe Plucky::Query do
|
|
290
315
|
context "#distinct" do
|
291
316
|
before do
|
292
317
|
# same age as John
|
293
|
-
@mark =
|
294
|
-
@collection.
|
318
|
+
@mark = Hash['_id', 'mark', 'age', 28, 'name', 'Mark']
|
319
|
+
@collection.insert_one(@mark)
|
295
320
|
end
|
296
321
|
|
297
322
|
it "works with just a key" do
|
@@ -489,23 +514,23 @@ describe Plucky::Query do
|
|
489
514
|
end
|
490
515
|
|
491
516
|
it "works with symbol operators" do
|
492
|
-
subject.sort(:foo.asc, :bar.desc).options[:sort].should ==
|
517
|
+
subject.sort(:foo.asc, :bar.desc).options[:sort].should == {"foo" => 1, "bar" => -1}
|
493
518
|
end
|
494
519
|
|
495
520
|
it "works with string" do
|
496
|
-
subject.sort('foo, bar desc').options[:sort].should ==
|
521
|
+
subject.sort('foo, bar desc').options[:sort].should == {"foo" => 1, "bar" => -1}
|
497
522
|
end
|
498
523
|
|
499
524
|
it "works with just a symbol" do
|
500
|
-
subject.sort(:foo).options[:sort].should ==
|
525
|
+
subject.sort(:foo).options[:sort].should == {"foo" => 1}
|
501
526
|
end
|
502
527
|
|
503
528
|
it "works with symbol descending" do
|
504
|
-
subject.sort(:foo.desc).options[:sort].should ==
|
529
|
+
subject.sort(:foo.desc).options[:sort].should == {"foo" => -1}
|
505
530
|
end
|
506
531
|
|
507
532
|
it "works with multiple symbols" do
|
508
|
-
subject.sort(:foo, :bar).options[:sort].should ==
|
533
|
+
subject.sort(:foo, :bar).options[:sort].should == {"foo" => 1, "bar" => 1}
|
509
534
|
end
|
510
535
|
|
511
536
|
it "returns new instance of query" do
|
@@ -515,8 +540,8 @@ describe Plucky::Query do
|
|
515
540
|
end
|
516
541
|
|
517
542
|
it "is aliased to order" do
|
518
|
-
subject.order(:foo).options[:sort].should ==
|
519
|
-
subject.order(:foo, :bar).options[:sort].should ==
|
543
|
+
subject.order(:foo).options[:sort].should == {"foo" => 1}
|
544
|
+
subject.order(:foo, :bar).options[:sort].should == {"foo" => 1, "bar" => 1}
|
520
545
|
end
|
521
546
|
end
|
522
547
|
|
@@ -529,27 +554,27 @@ describe Plucky::Query do
|
|
529
554
|
end
|
530
555
|
|
531
556
|
it "does not error if no sort provided" do
|
532
|
-
|
557
|
+
lambda {
|
533
558
|
subject.reverse
|
534
|
-
}.
|
559
|
+
}.should_not raise_error
|
535
560
|
end
|
536
561
|
|
537
562
|
it "reverses the sort order" do
|
538
563
|
subject.sort('foo asc, bar desc').
|
539
|
-
reverse.options[:sort].should ==
|
564
|
+
reverse.options[:sort].should == {"foo" => -1, "bar" => 1}
|
540
565
|
end
|
541
566
|
|
542
567
|
it "returns new instance of query" do
|
543
568
|
sorted_query = subject.sort(:name)
|
544
569
|
new_query = sorted_query.reverse
|
545
570
|
new_query.should_not equal(sorted_query)
|
546
|
-
sorted_query[:sort].should ==
|
571
|
+
sorted_query[:sort].should == {'name' => 1}
|
547
572
|
end
|
548
573
|
end
|
549
574
|
|
550
575
|
context "#amend" do
|
551
576
|
it "normalizes and update options" do
|
552
|
-
described_class.new(@collection).amend(:order => :age.desc).options[:sort].should ==
|
577
|
+
described_class.new(@collection).amend(:order => :age.desc).options[:sort].should == {'age' => -1}
|
553
578
|
end
|
554
579
|
|
555
580
|
it "works with simple stuff" do
|
@@ -611,7 +636,7 @@ describe Plucky::Query do
|
|
611
636
|
|
612
637
|
context "#empty?" do
|
613
638
|
it "returns true if empty" do
|
614
|
-
@collection.
|
639
|
+
@collection.drop
|
615
640
|
described_class.new(@collection).should be_empty
|
616
641
|
end
|
617
642
|
|
@@ -672,7 +697,7 @@ describe Plucky::Query do
|
|
672
697
|
it "returns a working enumerator" do
|
673
698
|
query = described_class.new(@collection)
|
674
699
|
query.each.methods.map(&:to_sym).include?(:group_by).should be(true)
|
675
|
-
query.each.next.should be_instance_of(BSON::
|
700
|
+
query.each.next.should be_instance_of(BSON::Document)
|
676
701
|
end
|
677
702
|
end
|
678
703
|
|
@@ -737,8 +762,8 @@ describe Plucky::Query do
|
|
737
762
|
end
|
738
763
|
|
739
764
|
{
|
740
|
-
:
|
741
|
-
:sort =>
|
765
|
+
:projection => {'foo' => 1},
|
766
|
+
:sort => {'foo' => 1},
|
742
767
|
:hint => '',
|
743
768
|
:skip => 0,
|
744
769
|
:limit => 0,
|
@@ -754,14 +779,14 @@ describe Plucky::Query do
|
|
754
779
|
|
755
780
|
it "knows select is an option and remove it from options" do
|
756
781
|
query = described_class.new(@collection, :select => 'foo')
|
757
|
-
query.options[:
|
782
|
+
query.options[:projection].should == {'foo' => 1}
|
758
783
|
query.criteria.keys.should_not include(:select)
|
759
784
|
query.options.keys.should_not include(:select)
|
760
785
|
end
|
761
786
|
|
762
787
|
it "knows order is an option and remove it from options" do
|
763
788
|
query = described_class.new(@collection, :order => 'foo')
|
764
|
-
query.options[:sort].should ==
|
789
|
+
query.options[:sort].should == {'foo' => 1}
|
765
790
|
query.criteria.keys.should_not include(:order)
|
766
791
|
query.options.keys.should_not include(:order)
|
767
792
|
end
|
@@ -777,15 +802,15 @@ describe Plucky::Query do
|
|
777
802
|
query = described_class.new(@collection, {
|
778
803
|
:foo => 'bar',
|
779
804
|
:baz => true,
|
780
|
-
:sort =>
|
805
|
+
:sort => {"foo" => 1},
|
781
806
|
:fields => ['foo', 'baz'],
|
782
807
|
:limit => 10,
|
783
808
|
:skip => 10,
|
784
809
|
})
|
785
810
|
query.criteria.source.should eq(:foo => 'bar', :baz => true)
|
786
811
|
query.options.source.should eq({
|
787
|
-
:sort =>
|
788
|
-
:
|
812
|
+
:sort => {"foo" => 1},
|
813
|
+
:projection => {'foo' => 1, 'baz' => 1},
|
789
814
|
:limit => 10,
|
790
815
|
:skip => 10,
|
791
816
|
})
|
@@ -815,8 +840,14 @@ describe Plucky::Query do
|
|
815
840
|
|
816
841
|
it "works" do
|
817
842
|
explain = subject.where(:age.lt => 28).explain
|
818
|
-
|
819
|
-
explain['
|
843
|
+
|
844
|
+
if explain['cursor']
|
845
|
+
explain['cursor'].should == 'BasicCursor'
|
846
|
+
explain['nscanned'].should == 3
|
847
|
+
elsif explain['executionStats']
|
848
|
+
explain['executionStats']['executionSuccess'].should == true
|
849
|
+
explain['executionStats']['totalDocsExamined'].should == 3
|
850
|
+
end
|
820
851
|
end
|
821
852
|
end
|
822
853
|
|
@@ -838,5 +869,31 @@ describe Plucky::Query do
|
|
838
869
|
result.should be_instance_of(@user_class)
|
839
870
|
end
|
840
871
|
end
|
872
|
+
|
873
|
+
it "works with block form of find_each" do
|
874
|
+
results = []
|
875
|
+
@query.find_each do |doc|
|
876
|
+
results << doc
|
877
|
+
end
|
878
|
+
results.each do |result|
|
879
|
+
result.should be_instance_of(@user_class)
|
880
|
+
end
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
884
|
+
describe "insert" do
|
885
|
+
before { @query = described_class.new(@collection) }
|
886
|
+
subject { @query }
|
887
|
+
|
888
|
+
it "should be able to insert one doc" do
|
889
|
+
subject.insert({ foo: 'bar' })
|
890
|
+
subject.count({ foo: 'bar' }).should == 1
|
891
|
+
end
|
892
|
+
|
893
|
+
it "should be able to insert multiple" do
|
894
|
+
subject.insert([{ foo: 'bar' }, { baz: 'quxx' }])
|
895
|
+
subject.count({ foo: 'bar' }).should == 1
|
896
|
+
subject.count({ baz: 'quxx' }).should == 1
|
897
|
+
end
|
841
898
|
end
|
842
899
|
end
|