plucky 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.bundle/config +4 -0
- data/.gitignore +3 -1
- data/.travis.yml +2 -2
- data/Gemfile +13 -3
- data/Guardfile +13 -0
- data/README.md +1 -1
- data/Rakefile +3 -17
- data/examples/query.rb +1 -1
- data/lib/plucky.rb +13 -0
- data/lib/plucky/criteria_hash.rb +85 -56
- data/lib/plucky/normalizers/criteria_hash_key.rb +17 -0
- data/lib/plucky/normalizers/criteria_hash_value.rb +83 -0
- data/lib/plucky/normalizers/fields_value.rb +26 -0
- data/lib/plucky/normalizers/integer.rb +19 -0
- data/lib/plucky/normalizers/options_hash_key.rb +23 -0
- data/lib/plucky/normalizers/options_hash_value.rb +85 -0
- data/lib/plucky/normalizers/sort_value.rb +55 -0
- data/lib/plucky/options_hash.rb +56 -85
- data/lib/plucky/pagination/decorator.rb +3 -2
- data/lib/plucky/pagination/paginator.rb +15 -6
- data/lib/plucky/query.rb +93 -51
- data/lib/plucky/version.rb +1 -1
- data/script/criteria_hash.rb +21 -0
- data/{test → spec}/helper.rb +12 -8
- data/spec/plucky/criteria_hash_spec.rb +166 -0
- data/spec/plucky/normalizers/criteria_hash_key_spec.rb +37 -0
- data/spec/plucky/normalizers/criteria_hash_value_spec.rb +193 -0
- data/spec/plucky/normalizers/fields_value_spec.rb +45 -0
- data/spec/plucky/normalizers/integer_spec.rb +24 -0
- data/spec/plucky/normalizers/options_hash_key_spec.rb +23 -0
- data/spec/plucky/normalizers/options_hash_value_spec.rb +99 -0
- data/spec/plucky/normalizers/sort_value_spec.rb +94 -0
- data/spec/plucky/options_hash_spec.rb +64 -0
- data/{test/plucky/pagination/test_decorator.rb → spec/plucky/pagination/decorator_spec.rb} +8 -10
- data/spec/plucky/pagination/paginator_spec.rb +118 -0
- data/spec/plucky/query_spec.rb +839 -0
- data/spec/plucky_spec.rb +68 -0
- data/{test/test_symbol_operator.rb → spec/symbol_operator_spec.rb} +14 -16
- data/spec/symbol_spec.rb +9 -0
- metadata +58 -23
- data/test/plucky/pagination/test_paginator.rb +0 -120
- data/test/plucky/test_criteria_hash.rb +0 -359
- data/test/plucky/test_options_hash.rb +0 -302
- data/test/plucky/test_query.rb +0 -843
- data/test/test_plucky.rb +0 -48
- data/test/test_symbol.rb +0 -11
data/lib/plucky/query.rb
CHANGED
@@ -1,36 +1,43 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
require 'set'
|
2
3
|
require 'forwardable'
|
4
|
+
|
3
5
|
module Plucky
|
4
6
|
class Query
|
5
7
|
include Enumerable
|
6
8
|
extend Forwardable
|
7
9
|
|
8
|
-
|
10
|
+
# Private
|
11
|
+
OptionKeys = Set[
|
9
12
|
:select, :offset, :order, # MM
|
10
13
|
:fields, :skip, :limit, :sort, :hint, :snapshot, # Ruby Driver
|
11
|
-
:batch_size, :timeout, :
|
12
|
-
:
|
14
|
+
:batch_size, :timeout, :max_scan, :return_key, # Ruby Driver
|
15
|
+
:transformer, :show_disk_loc, :comment, :read, # Ruby Driver
|
16
|
+
:tag_sets, :acceptable_latency, # Ruby Driver
|
13
17
|
]
|
14
18
|
|
15
19
|
attr_reader :criteria, :options, :collection
|
16
|
-
|
17
|
-
def_delegator
|
20
|
+
|
21
|
+
def_delegator :@criteria, :simple?
|
22
|
+
def_delegator :@options, :fields?
|
18
23
|
def_delegators :to_a, :include?
|
19
24
|
|
20
|
-
|
25
|
+
# Public
|
26
|
+
def initialize(collection, query_options = {})
|
21
27
|
@collection, @options, @criteria = collection, OptionsHash.new, CriteriaHash.new
|
22
|
-
|
28
|
+
query_options.each { |key, value| self[key] = value }
|
23
29
|
end
|
24
30
|
|
25
|
-
def initialize_copy(
|
31
|
+
def initialize_copy(original)
|
26
32
|
super
|
27
33
|
@criteria = @criteria.dup
|
28
34
|
@options = @options.dup
|
29
35
|
end
|
30
36
|
|
37
|
+
# Public
|
31
38
|
def object_ids(*keys)
|
32
|
-
return criteria.object_ids if keys.empty?
|
33
|
-
criteria.object_ids = *keys
|
39
|
+
return @criteria.object_ids if keys.empty?
|
40
|
+
@criteria.object_ids = *keys
|
34
41
|
self
|
35
42
|
end
|
36
43
|
|
@@ -48,30 +55,39 @@ module Plucky
|
|
48
55
|
limit = opts.delete(:per_page) || per_page
|
49
56
|
query = clone.amend(opts)
|
50
57
|
paginator = Pagination::Paginator.new(query.count, page, limit)
|
51
|
-
query.amend(
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
docs = query.amend({
|
59
|
+
:limit => paginator.limit,
|
60
|
+
:skip => paginator.skip,
|
61
|
+
}).all
|
62
|
+
|
63
|
+
docs.extend(Pagination::Decorator)
|
64
|
+
docs.paginator(paginator)
|
65
|
+
docs
|
55
66
|
end
|
56
67
|
|
57
68
|
def find_each(opts={}, &block)
|
58
69
|
query = clone.amend(opts)
|
59
|
-
cursor = query.
|
70
|
+
cursor = query.cursor
|
71
|
+
|
60
72
|
if block_given?
|
61
73
|
cursor.each { |doc| yield doc }
|
62
74
|
cursor.rewind!
|
63
75
|
end
|
76
|
+
|
64
77
|
cursor
|
65
78
|
end
|
66
79
|
|
67
80
|
def find_one(opts={})
|
68
81
|
query = clone.amend(opts)
|
69
|
-
query.collection.find_one(query.
|
82
|
+
query.collection.find_one(query.criteria_hash, query.options_hash)
|
70
83
|
end
|
71
84
|
|
72
85
|
def find(*ids)
|
73
86
|
return nil if ids.empty?
|
74
|
-
|
87
|
+
|
88
|
+
single_id_find = ids.size == 1 && !ids[0].is_a?(Array)
|
89
|
+
|
90
|
+
if single_id_find
|
75
91
|
first(:_id => ids[0])
|
76
92
|
else
|
77
93
|
all(:_id => ids.flatten)
|
@@ -96,12 +112,12 @@ module Plucky
|
|
96
112
|
|
97
113
|
def remove(opts={}, driver_opts={})
|
98
114
|
query = clone.amend(opts)
|
99
|
-
query.collection.remove(query.
|
115
|
+
query.collection.remove(query.criteria_hash, driver_opts)
|
100
116
|
end
|
101
117
|
|
102
118
|
def count(opts={})
|
103
119
|
query = clone.amend(opts)
|
104
|
-
cursor = query.
|
120
|
+
cursor = query.cursor
|
105
121
|
cursor.count
|
106
122
|
end
|
107
123
|
|
@@ -111,7 +127,7 @@ module Plucky
|
|
111
127
|
|
112
128
|
def distinct(key, opts = {})
|
113
129
|
query = clone.amend(opts)
|
114
|
-
query.collection.distinct(key, query.
|
130
|
+
query.collection.distinct(key, query.criteria_hash)
|
115
131
|
end
|
116
132
|
|
117
133
|
def fields(*args)
|
@@ -119,11 +135,11 @@ module Plucky
|
|
119
135
|
end
|
120
136
|
|
121
137
|
def ignore(*args)
|
122
|
-
|
138
|
+
set_field_inclusion(args, 0)
|
123
139
|
end
|
124
140
|
|
125
141
|
def only(*args)
|
126
|
-
|
142
|
+
set_field_inclusion(args, 1)
|
127
143
|
end
|
128
144
|
|
129
145
|
def limit(count=nil)
|
@@ -132,9 +148,10 @@ module Plucky
|
|
132
148
|
|
133
149
|
def reverse
|
134
150
|
clone.tap do |query|
|
135
|
-
|
136
|
-
|
137
|
-
|
151
|
+
sort = query[:sort]
|
152
|
+
unless sort.nil?
|
153
|
+
query.options[:sort] = sort.map { |s| [s[0], -s[1]] }
|
154
|
+
end
|
138
155
|
end
|
139
156
|
end
|
140
157
|
|
@@ -149,9 +166,7 @@ module Plucky
|
|
149
166
|
alias order sort
|
150
167
|
|
151
168
|
def where(hash={})
|
152
|
-
clone.tap
|
153
|
-
query.criteria.merge!(CriteriaHash.new(hash))
|
154
|
-
end
|
169
|
+
clone.tap { |query| query.criteria.merge!(CriteriaHash.new(hash)) }
|
155
170
|
end
|
156
171
|
alias filter where
|
157
172
|
|
@@ -159,8 +174,8 @@ module Plucky
|
|
159
174
|
count.zero?
|
160
175
|
end
|
161
176
|
|
162
|
-
def exists?(
|
163
|
-
!count(
|
177
|
+
def exists?(query_options={})
|
178
|
+
!count(query_options).zero?
|
164
179
|
end
|
165
180
|
alias :exist? :exists?
|
166
181
|
|
@@ -172,7 +187,7 @@ module Plucky
|
|
172
187
|
|
173
188
|
def update(document, driver_opts={})
|
174
189
|
query = clone
|
175
|
-
query.collection.update(query.
|
190
|
+
query.collection.update(query.criteria_hash, document, driver_opts)
|
176
191
|
end
|
177
192
|
|
178
193
|
def amend(opts={})
|
@@ -181,35 +196,29 @@ module Plucky
|
|
181
196
|
end
|
182
197
|
|
183
198
|
def [](key)
|
184
|
-
key = key
|
185
|
-
|
186
|
-
|
187
|
-
else
|
188
|
-
@criteria[key]
|
189
|
-
end
|
199
|
+
key = symbolized_key(key)
|
200
|
+
source = hash_for_key(key)
|
201
|
+
source[key]
|
190
202
|
end
|
191
203
|
|
192
204
|
def []=(key, value)
|
193
|
-
key = key
|
194
|
-
|
195
|
-
|
196
|
-
else
|
197
|
-
@criteria[key] = value
|
198
|
-
end
|
205
|
+
key = symbolized_key(key)
|
206
|
+
source = hash_for_key(key)
|
207
|
+
source[key] = value
|
199
208
|
end
|
200
209
|
|
201
210
|
def merge(other)
|
202
|
-
merged_criteria = criteria.merge(other.criteria).to_hash
|
203
|
-
merged_options = options.merge(other.options).to_hash
|
211
|
+
merged_criteria = @criteria.merge(other.criteria).to_hash
|
212
|
+
merged_options = @options.merge(other.options).to_hash
|
204
213
|
clone.amend(merged_criteria).amend(merged_options)
|
205
214
|
end
|
206
215
|
|
207
216
|
def to_hash
|
208
|
-
|
217
|
+
criteria_hash.merge(options_hash)
|
209
218
|
end
|
210
219
|
|
211
220
|
def explain
|
212
|
-
collection.find(
|
221
|
+
@collection.find(criteria_hash, options_hash).explain
|
213
222
|
end
|
214
223
|
|
215
224
|
def inspect
|
@@ -219,11 +228,44 @@ module Plucky
|
|
219
228
|
"#<#{self.class}#{as_nice_string}>"
|
220
229
|
end
|
221
230
|
|
231
|
+
def criteria_hash
|
232
|
+
@criteria.to_hash
|
233
|
+
end
|
234
|
+
|
235
|
+
def options_hash
|
236
|
+
@options.to_hash
|
237
|
+
end
|
238
|
+
|
239
|
+
def cursor
|
240
|
+
@collection.find(criteria_hash, options_hash)
|
241
|
+
end
|
242
|
+
|
222
243
|
private
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
244
|
+
|
245
|
+
# Private
|
246
|
+
def hash_for_key(key)
|
247
|
+
options_key?(key) ? @options : @criteria
|
248
|
+
end
|
249
|
+
|
250
|
+
# Private
|
251
|
+
def symbolized_key(key)
|
252
|
+
if key.respond_to?(:to_sym)
|
253
|
+
key.to_sym
|
254
|
+
else
|
255
|
+
key
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Private
|
260
|
+
def options_key?(key)
|
261
|
+
OptionKeys.include?(key)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Private
|
265
|
+
def set_field_inclusion(fields, value)
|
266
|
+
fields_option = {}
|
267
|
+
fields.each { |field| fields_option[symbolized_key(field)] = value }
|
268
|
+
clone.tap { |query| query.options[:fields] = fields_option }
|
227
269
|
end
|
228
270
|
end
|
229
271
|
end
|
data/lib/plucky/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'pathname'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
|
7
|
+
Bundler.require :default, :performance
|
8
|
+
|
9
|
+
root_path = Pathname(__FILE__).dirname.join('..').expand_path
|
10
|
+
lib_path = root_path.join('lib')
|
11
|
+
$:.unshift(lib_path)
|
12
|
+
require 'plucky'
|
13
|
+
|
14
|
+
criteria = Plucky::CriteriaHash.new(:foo => 'bar')
|
15
|
+
|
16
|
+
PerfTools::CpuProfiler.start("/tmp/criteria_hash") do
|
17
|
+
1_000_000.times { criteria[:foo] = 'bar' }
|
18
|
+
end
|
19
|
+
|
20
|
+
puts system "pprof.rb --gif /tmp/criteria_hash > /tmp/criteria_hash.gif"
|
21
|
+
puts system "open /tmp/criteria_hash.gif"
|
data/{test → spec}/helper.rb
RENAMED
@@ -1,15 +1,15 @@
|
|
1
|
+
$:.unshift(File.expand_path('../../lib', __FILE__))
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'bundler'
|
3
5
|
|
4
6
|
Bundler.require(:default, :test)
|
5
7
|
|
6
|
-
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
7
8
|
require 'plucky'
|
8
9
|
|
9
10
|
require 'fileutils'
|
10
11
|
require 'logger'
|
11
12
|
require 'pp'
|
12
|
-
require 'set'
|
13
13
|
|
14
14
|
log_dir = File.expand_path('../../log', __FILE__)
|
15
15
|
FileUtils.mkdir_p(log_dir)
|
@@ -20,17 +20,21 @@ LogBuddy.init :logger => Log
|
|
20
20
|
connection = Mongo::Connection.new('127.0.0.1', 27017, :logger => Log)
|
21
21
|
DB = connection.db('test')
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.filter_run :focused => true
|
25
|
+
config.alias_example_to :fit, :focused => true
|
26
|
+
config.alias_example_to :xit, :pending => true
|
27
|
+
config.run_all_when_everything_filtered = true
|
28
|
+
|
29
|
+
config.before(:suite) do
|
25
30
|
DB.collections.map do |collection|
|
26
|
-
collection.remove
|
27
31
|
collection.drop_indexes
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
config.before(:each) do
|
36
|
+
DB.collections.map do |collection|
|
37
|
+
collection.remove
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Plucky::CriteriaHash do
|
4
|
+
context "#initialize_copy" do
|
5
|
+
before do
|
6
|
+
@original = described_class.new({
|
7
|
+
:comments => {:_id => 1}, :tags => ['mongo', 'ruby'],
|
8
|
+
}, :object_ids => [:_id])
|
9
|
+
@cloned = @original.clone
|
10
|
+
end
|
11
|
+
|
12
|
+
it "duplicates source hash" do
|
13
|
+
@cloned.source.should_not equal(@original.source)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "duplicates options hash" do
|
17
|
+
@cloned.options.should_not equal(@original.options)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "clones duplicable? values" do
|
21
|
+
@cloned[:comments].should_not equal(@original[:comments])
|
22
|
+
@cloned[:tags].should_not equal(@original[:tags])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "#object_ids=" do
|
27
|
+
it "works with array" do
|
28
|
+
criteria = described_class.new
|
29
|
+
criteria.object_ids = [:_id]
|
30
|
+
criteria.object_ids.should == [:_id]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "flattens multi-dimensional array" do
|
34
|
+
criteria = described_class.new
|
35
|
+
criteria.object_ids = [[:_id]]
|
36
|
+
criteria.object_ids.should == [:_id]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "raises argument error if not array" do
|
40
|
+
expect { described_class.new.object_ids = {} }.to raise_error(ArgumentError)
|
41
|
+
expect { described_class.new.object_ids = nil }.to raise_error(ArgumentError)
|
42
|
+
expect { described_class.new.object_ids = 'foo' }.to raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "#[]=" do
|
47
|
+
context "with key and value" do
|
48
|
+
let(:key_normalizer) { lambda { |*args| :normalized_key } }
|
49
|
+
let(:value_normalizer) { lambda { |*args| 'normalized_value' } }
|
50
|
+
|
51
|
+
it "sets normalized key to normalized value in source" do
|
52
|
+
criteria = described_class.new({}, :value_normalizer => value_normalizer, :key_normalizer => key_normalizer)
|
53
|
+
criteria[:foo] = 'bar'
|
54
|
+
criteria.source[:normalized_key].should eq('normalized_value')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with conditions" do
|
59
|
+
it "sets each of conditions keys in source" do
|
60
|
+
criteria = described_class.new
|
61
|
+
criteria[:conditions] = {:_id => 'john', :foo => 'bar'}
|
62
|
+
criteria.source[:_id].should eq('john')
|
63
|
+
criteria.source[:foo].should eq('bar')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with symbol operators" do
|
68
|
+
it "sets nests key with operator and value" do
|
69
|
+
criteria = described_class.new
|
70
|
+
criteria[:age.gt] = 20
|
71
|
+
criteria[:age.lt] = 10
|
72
|
+
criteria.source[:age].should eq({:$gt => 20, :$lt => 10})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "#merge" do
|
78
|
+
it "works when no keys match" do
|
79
|
+
c1 = described_class.new(:foo => 'bar')
|
80
|
+
c2 = described_class.new(:baz => 'wick')
|
81
|
+
c1.merge(c2).source.should eq(:foo => 'bar', :baz => 'wick')
|
82
|
+
end
|
83
|
+
|
84
|
+
it "turns matching keys with simple values into array" do
|
85
|
+
c1 = described_class.new(:foo => 'bar')
|
86
|
+
c2 = described_class.new(:foo => 'baz')
|
87
|
+
c1.merge(c2).source.should eq(:foo => {:$in => %w[bar baz]})
|
88
|
+
end
|
89
|
+
|
90
|
+
it "uniques matching key values" do
|
91
|
+
c1 = described_class.new(:foo => 'bar')
|
92
|
+
c2 = described_class.new(:foo => 'bar')
|
93
|
+
c1.merge(c2).source.should eq(:foo => {:$in => %w[bar]})
|
94
|
+
end
|
95
|
+
|
96
|
+
it "correctly merges arrays and non-arrays" do
|
97
|
+
c1 = described_class.new(:foo => 'bar')
|
98
|
+
c2 = described_class.new(:foo => %w[bar baz])
|
99
|
+
c1.merge(c2).source.should eq(:foo => {:$in => %w[bar baz]})
|
100
|
+
c2.merge(c1).source.should eq(:foo => {:$in => %w[bar baz]})
|
101
|
+
end
|
102
|
+
|
103
|
+
it "is able to merge two modifier hashes" do
|
104
|
+
c1 = described_class.new(:$in => [1, 2])
|
105
|
+
c2 = described_class.new(:$in => [2, 3])
|
106
|
+
c1.merge(c2).source.should eq(:$in => [1, 2, 3])
|
107
|
+
end
|
108
|
+
|
109
|
+
it "is able to merge two modifier hashes with hash values" do
|
110
|
+
c1 = described_class.new(:arr => {:$elemMatch => {:foo => 'bar'}})
|
111
|
+
c2 = described_class.new(:arr => {:$elemMatch => {:omg => 'ponies'}})
|
112
|
+
c1.merge(c2).source.should eq(:arr => {:$elemMatch => {:foo => 'bar', :omg => 'ponies'}})
|
113
|
+
end
|
114
|
+
|
115
|
+
it "merges matching keys with a single modifier" do
|
116
|
+
c1 = described_class.new(:foo => {:$in => [1, 2, 3]})
|
117
|
+
c2 = described_class.new(:foo => {:$in => [1, 4, 5]})
|
118
|
+
c1.merge(c2).source.should eq(:foo => {:$in => [1, 2, 3, 4, 5]})
|
119
|
+
end
|
120
|
+
|
121
|
+
it "merges matching keys with multiple modifiers" do
|
122
|
+
c1 = described_class.new(:foo => {:$in => [1, 2, 3]})
|
123
|
+
c2 = described_class.new(:foo => {:$all => [1, 4, 5]})
|
124
|
+
c1.merge(c2).source.should eq(:foo => {:$in => [1, 2, 3], :$all => [1, 4, 5]})
|
125
|
+
end
|
126
|
+
|
127
|
+
it "does not update mergee" do
|
128
|
+
c1 = described_class.new(:foo => 'bar')
|
129
|
+
c2 = described_class.new(:foo => 'baz')
|
130
|
+
c1.merge(c2).should_not equal(c1)
|
131
|
+
c1[:foo].should == 'bar'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "#merge!" do
|
136
|
+
it "updates mergee" do
|
137
|
+
c1 = described_class.new(:foo => 'bar')
|
138
|
+
c2 = described_class.new(:foo => 'baz')
|
139
|
+
c1.merge!(c2).should equal(c1)
|
140
|
+
c1[:foo].should == {:$in => ['bar', 'baz']}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "#simple?" do
|
145
|
+
it "returns true if only filtering by _id" do
|
146
|
+
described_class.new(:_id => 'id').should be_simple
|
147
|
+
end
|
148
|
+
|
149
|
+
it "returns true if only filtering by Sci" do
|
150
|
+
described_class.new(:_id => 'id', :_type => 'Foo').should be_simple
|
151
|
+
described_class.new(:_type => 'Foo', :_id => 'id').should be_simple # reverse order
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns false if querying by more than max number of simple keys" do
|
155
|
+
described_class.new(:one => 1, :two => 2, :three => 3).should_not be_simple
|
156
|
+
end
|
157
|
+
|
158
|
+
it "returns false if querying by anthing other than _id/Sci" do
|
159
|
+
described_class.new(:foo => 'bar').should_not be_simple
|
160
|
+
end
|
161
|
+
|
162
|
+
it "returns false if querying only by _type" do
|
163
|
+
described_class.new(:_type => 'Foo').should_not be_simple
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|