mongoid 6.4.1 → 6.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongoid/contextual/map_reduce.rb +1 -1
- data/lib/mongoid/criteria/modifiable.rb +12 -2
- data/lib/mongoid/criteria/queryable/selectable.rb +1 -1
- data/lib/mongoid/matchable.rb +3 -0
- data/lib/mongoid/matchable/nor.rb +37 -0
- data/lib/mongoid/persistable/settable.rb +5 -5
- data/lib/mongoid/persistence_context.rb +4 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/app/models/array_field.rb +7 -0
- data/spec/mongoid/clients/factory_spec.rb +3 -3
- data/spec/mongoid/clients/options_spec.rb +28 -13
- data/spec/mongoid/clients/sessions_spec.rb +3 -3
- data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
- data/spec/mongoid/matchable/nor_spec.rb +209 -0
- data/spec/mongoid/matchable_spec.rb +26 -1
- data/spec/mongoid/persistable/settable_spec.rb +19 -0
- metadata +451 -446
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4c5d349e3de6af570dd7b1347fd76b6056848149180dc355e116f67f8ac2c3c6
|
4
|
+
data.tar.gz: e9be28598f701bb124ba6626bb777da07d05bca692224110078700557f2c0aa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bf33975f8969cc06ac717cef1a443429dd6ad8e8a7cd755c8b74ed9b7bc0e1a113413dac81098f54f9c181b91d03fc5958adfaaddb03d7fb91caa9f2e11dc84
|
7
|
+
data.tar.gz: c5ef0576ed9941a5ba0f0865fdaff885766e4d6fe6901d1037ce408a0acdc0e00fdbfe503a5a7d721d8178a83c39c6e5893aaf0c258e871b3dca17939d0e7d97
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
@@ -165,7 +165,7 @@ module Mongoid
|
|
165
165
|
def raw
|
166
166
|
validate_out!
|
167
167
|
cmd = command
|
168
|
-
opts = { read: cmd.delete(:read)
|
168
|
+
opts = { read: cmd.delete(:read) } if cmd[:read]
|
169
169
|
@map_reduce.database.command(cmd, (opts || {}).merge(session: _session)).first
|
170
170
|
end
|
171
171
|
alias :results :raw
|
@@ -3,6 +3,10 @@ module Mongoid
|
|
3
3
|
class Criteria
|
4
4
|
module Modifiable
|
5
5
|
|
6
|
+
# @attribute [r] create_attrs Additional attributes to add to the Document upon creation.
|
7
|
+
# @api private
|
8
|
+
attr_reader :create_attrs
|
9
|
+
|
6
10
|
# Build a document given the selector and return it.
|
7
11
|
# Complex criteria, such as $in and $or operations will get ignored.
|
8
12
|
#
|
@@ -57,6 +61,9 @@ module Mongoid
|
|
57
61
|
|
58
62
|
# Define attributes with which new documents will be created.
|
59
63
|
#
|
64
|
+
# Note that if `find_or_create_by` is called after this in a method chain, the attributes in
|
65
|
+
# the query will override those from this method.
|
66
|
+
#
|
60
67
|
# @example Define attributes to be used when a new document is created.
|
61
68
|
# Person.create_with(job: 'Engineer').find_or_create_by(employer: 'MongoDB')
|
62
69
|
#
|
@@ -64,7 +71,9 @@ module Mongoid
|
|
64
71
|
#
|
65
72
|
# @since 5.1.0
|
66
73
|
def create_with(attrs = {})
|
67
|
-
|
74
|
+
tap do
|
75
|
+
(@create_attrs ||= {}).merge!(attrs)
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
70
79
|
# Find the first +Document+ given the conditions, or creates a new document
|
@@ -172,7 +181,8 @@ module Mongoid
|
|
172
181
|
#
|
173
182
|
# @since 3.0.0
|
174
183
|
def create_document(method, attrs = nil, &block)
|
175
|
-
|
184
|
+
attrs = (create_attrs || {}).merge(attrs || {})
|
185
|
+
attributes = selector.reduce(attrs) do |hash, (key, value)|
|
176
186
|
unless invalid_key?(hash, key) || invalid_embedded_doc?(value)
|
177
187
|
hash[key] = value
|
178
188
|
end
|
@@ -24,7 +24,7 @@ module Mongoid
|
|
24
24
|
# @since 2.0.0
|
25
25
|
POLYGON = "Polygon"
|
26
26
|
|
27
|
-
# @attribute [rw] negating If the next
|
27
|
+
# @attribute [rw] negating If the next expression is negated.
|
28
28
|
# @attribute [rw] selector The query selector.
|
29
29
|
attr_accessor :negating, :selector
|
30
30
|
|
data/lib/mongoid/matchable.rb
CHANGED
@@ -11,6 +11,7 @@ require "mongoid/matchable/lte"
|
|
11
11
|
require "mongoid/matchable/ne"
|
12
12
|
require "mongoid/matchable/nin"
|
13
13
|
require "mongoid/matchable/or"
|
14
|
+
require "mongoid/matchable/nor"
|
14
15
|
require "mongoid/matchable/size"
|
15
16
|
require "mongoid/matchable/elem_match"
|
16
17
|
require "mongoid/matchable/regexp"
|
@@ -40,6 +41,7 @@ module Mongoid
|
|
40
41
|
"$ne" => Ne,
|
41
42
|
"$nin" => Nin,
|
42
43
|
"$or" => Or,
|
44
|
+
"$nor" => Nor,
|
43
45
|
"$size" => Size
|
44
46
|
}.with_indifferent_access.freeze
|
45
47
|
|
@@ -124,6 +126,7 @@ module Mongoid
|
|
124
126
|
case key.to_s
|
125
127
|
when "$or" then Or.new(value, document)
|
126
128
|
when "$and" then And.new(value, document)
|
129
|
+
when "$nor" then Nor.new(value, document)
|
127
130
|
else Default.new(extract_attribute(document, key))
|
128
131
|
end
|
129
132
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
module Mongoid
|
4
|
+
module Matchable
|
5
|
+
|
6
|
+
# Defines behavior for handling $nor expressions in embedded documents.
|
7
|
+
class Nor < Default
|
8
|
+
|
9
|
+
# Does the supplied query match the attribute?
|
10
|
+
#
|
11
|
+
# Note: an empty array as an argument to $nor is prohibited by
|
12
|
+
# MongoDB server. Mongoid does allow this and returns false in this case.
|
13
|
+
#
|
14
|
+
# @example Does this match?
|
15
|
+
# matcher._matches?("$nor" => [ { field => value } ])
|
16
|
+
#
|
17
|
+
# @param [ Array ] conditions The or expression.
|
18
|
+
#
|
19
|
+
# @return [ true, false ] True if matches, false if not.
|
20
|
+
#
|
21
|
+
# @since 6.4.2/7.0.2/7.1.0
|
22
|
+
def _matches?(conditions)
|
23
|
+
if conditions.length == 0
|
24
|
+
# MongoDB does not allow $nor array to be empty, but
|
25
|
+
# Mongoid accepts an empty array for $or which MongoDB also
|
26
|
+
# prohibits
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
conditions.none? do |condition|
|
30
|
+
condition.all? do |key, value|
|
31
|
+
document._matches?(key => value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -25,15 +25,15 @@ module Mongoid
|
|
25
25
|
|
26
26
|
field_and_value_hash = hasherizer(field.split('.'), value)
|
27
27
|
field = field_and_value_hash.keys.first.to_s
|
28
|
+
value = field_and_value_hash[field]
|
28
29
|
|
29
|
-
if fields[field] && fields[field].type == Hash && attributes.key?(field) && !value.empty?
|
30
|
+
if fields[field] && fields[field].type == Hash && attributes.key?(field) && Hash === value && !value.empty?
|
30
31
|
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
31
|
-
value = (attributes[field] || {}).merge(
|
32
|
-
process_attribute(field.to_s, value)
|
33
|
-
else
|
34
|
-
process_attribute(field.to_s, field_and_value_hash[field])
|
32
|
+
value = (attributes[field] || {}).merge(value, &merger)
|
35
33
|
end
|
36
34
|
|
35
|
+
process_attribute(field.to_s, value)
|
36
|
+
|
37
37
|
unless relations.include?(field.to_s)
|
38
38
|
ops[atomic_attribute_name(field)] = attributes[field]
|
39
39
|
end
|
@@ -107,6 +107,10 @@ module Mongoid
|
|
107
107
|
#
|
108
108
|
# @since 6.0.0
|
109
109
|
def client
|
110
|
+
client_options = send(:client_options)
|
111
|
+
if client_options[:read].is_a?(Symbol)
|
112
|
+
client_options = client_options.merge(read: {mode: client_options[:read]})
|
113
|
+
end
|
110
114
|
@client ||= (client = Clients.with_name(client_name)
|
111
115
|
client = client.use(database_name) if database_name_option
|
112
116
|
client.with(client_options))
|
data/lib/mongoid/version.rb
CHANGED
@@ -132,8 +132,8 @@ describe Mongoid::Clients::Factory do
|
|
132
132
|
|
133
133
|
let(:config) do
|
134
134
|
{
|
135
|
-
default: { hosts: [ "127.0.0.1:
|
136
|
-
secondary: { uri: "mongodb://127.0.0.1:
|
135
|
+
default: { hosts: [ "127.0.0.1:1234" ], database: database_id },
|
136
|
+
secondary: { uri: "mongodb://127.0.0.1:1234,127.0.0.1:5678/mongoid_test" }
|
137
137
|
}
|
138
138
|
end
|
139
139
|
|
@@ -162,7 +162,7 @@ describe Mongoid::Clients::Factory do
|
|
162
162
|
end
|
163
163
|
|
164
164
|
it "sets the cluster's seeds" do
|
165
|
-
expect(seeds).to eq([ "127.0.0.1:
|
165
|
+
expect(seeds).to eq([ "127.0.0.1:1234", "127.0.0.1:5678" ])
|
166
166
|
end
|
167
167
|
end
|
168
168
|
end
|
@@ -177,25 +177,40 @@ describe Mongoid::Clients::Options do
|
|
177
177
|
|
178
178
|
context 'when returning a criteria' do
|
179
179
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
collection =
|
184
|
-
klass
|
180
|
+
shared_context 'applies secondary read preference' do
|
181
|
+
|
182
|
+
let(:context_and_criteria) do
|
183
|
+
collection = nil
|
184
|
+
cxt = Band.with(read_secondary_option) do |klass|
|
185
|
+
collection = klass.all.collection
|
186
|
+
klass.persistence_context
|
187
|
+
end
|
188
|
+
[ cxt, collection ]
|
185
189
|
end
|
186
|
-
[ cxt, collection ]
|
187
|
-
end
|
188
190
|
|
189
|
-
|
190
|
-
|
191
|
+
let(:persistence_context) do
|
192
|
+
context_and_criteria[0]
|
193
|
+
end
|
194
|
+
|
195
|
+
let(:client) do
|
196
|
+
context_and_criteria[1].client
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'applies the options to the criteria client' do
|
200
|
+
expect(client.options['read']).to eq('mode' => :secondary)
|
201
|
+
end
|
191
202
|
end
|
192
203
|
|
193
|
-
|
194
|
-
|
204
|
+
context 'read: :secondary shorthand' do
|
205
|
+
let(:read_secondary_option) { {read: :secondary} }
|
206
|
+
|
207
|
+
it_behaves_like 'applies secondary read preference'
|
195
208
|
end
|
196
209
|
|
197
|
-
|
198
|
-
|
210
|
+
context 'read: {mode: :secondary}' do
|
211
|
+
let(:read_secondary_option) { {read: {mode: :secondary}} }
|
212
|
+
|
213
|
+
it_behaves_like 'applies secondary read preference'
|
199
214
|
end
|
200
215
|
end
|
201
216
|
|
@@ -16,17 +16,17 @@ describe Mongoid::Clients::Sessions do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
let(:subscriber) do
|
19
|
-
Mongoid::Clients.with_name(:other).
|
19
|
+
Mongoid::Clients.with_name(:other).send(:monitoring).subscribers['Command'].find do |s|
|
20
20
|
s.is_a?(EventSubscriber)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
let(:insert_events) do
|
25
|
-
subscriber.started_events.select { |event| event.command_name ==
|
25
|
+
subscriber.started_events.select { |event| event.command_name == 'insert' }
|
26
26
|
end
|
27
27
|
|
28
28
|
let(:update_events) do
|
29
|
-
subscriber.started_events.select { |event| event.command_name ==
|
29
|
+
subscriber.started_events.select { |event| event.command_name == 'update' }
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when a session is used on a model class' do
|
@@ -1471,11 +1471,15 @@ describe Mongoid::Criteria::Modifiable do
|
|
1471
1471
|
{ 'username' => 'Turnip' }
|
1472
1472
|
end
|
1473
1473
|
|
1474
|
-
it '
|
1475
|
-
expect(Person.create_with(attrs).selector).to
|
1474
|
+
it 'does not modify the selector' do
|
1475
|
+
expect(Person.create_with(attrs).selector[:username]).to be_nil
|
1476
1476
|
end
|
1477
1477
|
|
1478
|
-
|
1478
|
+
it 'create_attrs is modified' do
|
1479
|
+
expect(Person.create_with(attrs).create_attrs).to eq(attrs)
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
context 'when a create is chained' do
|
1479
1483
|
|
1480
1484
|
context 'when a write method is chained' do
|
1481
1485
|
|
@@ -1499,6 +1503,25 @@ describe Mongoid::Criteria::Modifiable do
|
|
1499
1503
|
expect(new_person.age).to eq(50)
|
1500
1504
|
end
|
1501
1505
|
|
1506
|
+
context 'when a matching document is already in the collection' do
|
1507
|
+
let(:query) do
|
1508
|
+
{ 'username' => 'foo', 'age' => 12 }
|
1509
|
+
end
|
1510
|
+
|
1511
|
+
let(:person) do
|
1512
|
+
Person.create!(query)
|
1513
|
+
end
|
1514
|
+
|
1515
|
+
let(:found_person) do
|
1516
|
+
Person.create_with(attrs).find_or_create_by(query)
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
it 'finds the matching document' do
|
1520
|
+
person
|
1521
|
+
expect(found_person.id).to eq(person.id)
|
1522
|
+
end
|
1523
|
+
end
|
1524
|
+
|
1502
1525
|
context 'when the attributes are shared with the write method args' do
|
1503
1526
|
|
1504
1527
|
let(:query) do
|
@@ -1509,7 +1532,7 @@ describe Mongoid::Criteria::Modifiable do
|
|
1509
1532
|
Person.create_with(attrs).find_or_create_by(query)
|
1510
1533
|
end
|
1511
1534
|
|
1512
|
-
it 'gives the
|
1535
|
+
it 'gives the find method args precedence' do
|
1513
1536
|
expect(new_person.username).to eq('Beet')
|
1514
1537
|
expect(new_person.age).to eq(50)
|
1515
1538
|
end
|
@@ -1536,8 +1559,12 @@ describe Mongoid::Criteria::Modifiable do
|
|
1536
1559
|
{ 'username' => 'Beet', 'age' => 50 }
|
1537
1560
|
end
|
1538
1561
|
|
1562
|
+
it 'does not modify the selector' do
|
1563
|
+
expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
|
1564
|
+
end
|
1565
|
+
|
1539
1566
|
it 'overwrites all the original attributes' do
|
1540
|
-
expect(criteria.create_with(attrs).
|
1567
|
+
expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
|
1541
1568
|
end
|
1542
1569
|
end
|
1543
1570
|
end
|
@@ -1548,8 +1575,12 @@ describe Mongoid::Criteria::Modifiable do
|
|
1548
1575
|
{ 'username' => 'Beet' }
|
1549
1576
|
end
|
1550
1577
|
|
1578
|
+
it 'does not modify the selector' do
|
1579
|
+
expect(criteria.create_with(attrs).selector).to eq(criteria_selector)
|
1580
|
+
end
|
1581
|
+
|
1551
1582
|
it 'only overwrites the shared attributes' do
|
1552
|
-
expect(criteria.create_with(attrs).
|
1583
|
+
expect(criteria.create_with(attrs).create_attrs).to eq(attrs)
|
1553
1584
|
end
|
1554
1585
|
end
|
1555
1586
|
|
@@ -1558,12 +1589,11 @@ describe Mongoid::Criteria::Modifiable do
|
|
1558
1589
|
let(:attrs) do
|
1559
1590
|
{ 'username' => 'Turnip' }
|
1560
1591
|
end
|
1561
|
-
|
1562
1592
|
let(:query) do
|
1563
1593
|
{ 'username' => 'Beet', 'age' => 50 }
|
1564
1594
|
end
|
1565
1595
|
|
1566
|
-
context 'when a
|
1596
|
+
context 'when a create method is chained' do
|
1567
1597
|
|
1568
1598
|
it 'executes the method' do
|
1569
1599
|
expect(criteria.create_with(attrs).new.username).to eq('Turnip')
|
@@ -1577,9 +1607,28 @@ describe Mongoid::Criteria::Modifiable do
|
|
1577
1607
|
criteria.create_with(attrs).find_or_create_by(query)
|
1578
1608
|
end
|
1579
1609
|
|
1580
|
-
it '
|
1610
|
+
it 'gives the find method arg precedence' do
|
1581
1611
|
expect(new_person.username).to eq('Beet')
|
1582
|
-
expect(new_person.age).to
|
1612
|
+
expect(new_person.age).to be(50)
|
1613
|
+
end
|
1614
|
+
|
1615
|
+
context 'when a matching document is already in the collection' do
|
1616
|
+
let(:query) do
|
1617
|
+
{ 'username' => 'foo', 'age' => 12 }
|
1618
|
+
end
|
1619
|
+
|
1620
|
+
let(:person) do
|
1621
|
+
Person.create!(query)
|
1622
|
+
end
|
1623
|
+
|
1624
|
+
let(:found_person) do
|
1625
|
+
criteria.create_with(attrs).find_or_create_by(query)
|
1626
|
+
end
|
1627
|
+
|
1628
|
+
it 'finds the matching document' do
|
1629
|
+
person
|
1630
|
+
expect(found_person.id).to eq(person.id)
|
1631
|
+
end
|
1583
1632
|
end
|
1584
1633
|
end
|
1585
1634
|
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Mongoid::Matchable::Nor do
|
6
|
+
|
7
|
+
let(:target) do
|
8
|
+
Person.new
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:matcher) do
|
12
|
+
described_class.new("value", target)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#_matches?" do
|
16
|
+
|
17
|
+
context "when provided a simple expression" do
|
18
|
+
|
19
|
+
context "when one of the hashes does not match model" do
|
20
|
+
|
21
|
+
let(:matches) do
|
22
|
+
matcher._matches?(
|
23
|
+
[ { title: "Sir" }, { title: "King" } ]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:target) do
|
28
|
+
Person.new(title: 'Queen')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns true" do
|
32
|
+
expect(matches).to be true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when all of the hashes match different fields in model" do
|
37
|
+
let(:matches) do
|
38
|
+
matcher._matches?(
|
39
|
+
[ { age: 10 }, { title: "King" } ]
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:target) do
|
44
|
+
Person.new(title: 'King', age: 10)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns false" do
|
48
|
+
expect(matches).to be false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when one of the hashes matches an array field in model" do
|
53
|
+
let(:matches) do
|
54
|
+
matcher._matches?(
|
55
|
+
[ { af: "Sir" }, { af: "King" } ]
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
let(:target) do
|
60
|
+
ArrayField.new(af: ['King'])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns false" do
|
64
|
+
expect(matches).to be false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when none of the hashes matches an array field in model" do
|
69
|
+
let(:matches) do
|
70
|
+
matcher._matches?(
|
71
|
+
[ { af: "Sir" }, { af: "King" } ]
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:target) do
|
76
|
+
ArrayField.new(af: ['Boo'])
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns true" do
|
80
|
+
expect(matches).to be true
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when there are no criteria" do
|
85
|
+
|
86
|
+
it "returns false" do
|
87
|
+
expect(matcher._matches?([])).to be false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# $nor with $not is a double negation.
|
92
|
+
# Whatever the argument of $not is is what the overall condition
|
93
|
+
# is looking for.
|
94
|
+
context "when the expression is a $not" do
|
95
|
+
|
96
|
+
let(:matches) do
|
97
|
+
matcher._matches?([ { title: {:$not => /Foobar/ } }])
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when the value does not match $not argument" do
|
101
|
+
|
102
|
+
let(:target) do
|
103
|
+
Person.new(title: 'test')
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns false" do
|
107
|
+
expect(matches).to be false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when the value matches $not argument" do
|
112
|
+
|
113
|
+
let(:target) do
|
114
|
+
Person.new(title: 'Foobar baz')
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns true" do
|
118
|
+
expect(matches).to be true
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when provided a complex expression" do
|
125
|
+
|
126
|
+
context "when none of the model values match criteria values" do
|
127
|
+
|
128
|
+
let(:matches) do
|
129
|
+
matcher._matches?(
|
130
|
+
[
|
131
|
+
{ title: { "$in" => [ "Sir", "Madam" ] } },
|
132
|
+
{ title: "King" }
|
133
|
+
]
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
let(:target) do
|
138
|
+
Person.new(title: 'Queen')
|
139
|
+
end
|
140
|
+
|
141
|
+
it "returns true" do
|
142
|
+
expect(matches).to be true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when there is a matching value" do
|
147
|
+
|
148
|
+
let(:matches) do
|
149
|
+
matcher._matches?(
|
150
|
+
[
|
151
|
+
{ title: { "$in" => [ "Prince", "Madam" ] } },
|
152
|
+
{ title: "King" }
|
153
|
+
]
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
let(:target) do
|
158
|
+
Person.new(title: 'Prince')
|
159
|
+
end
|
160
|
+
|
161
|
+
it "returns false" do
|
162
|
+
expect(matches).to be false
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "when expression contain multiple fields" do
|
167
|
+
|
168
|
+
let(:matches) do
|
169
|
+
matcher._matches?(
|
170
|
+
[
|
171
|
+
{ title: "Sir", age: 23 },
|
172
|
+
{ title: "King", age: 100 }
|
173
|
+
]
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'and model has different values in all of the fields' do
|
178
|
+
let(:target) do
|
179
|
+
Person.new(title: 'Queen', age: 10)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "returns true" do
|
183
|
+
expect(matches).to be true
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'and model has identical value in one of the fields' do
|
188
|
+
let(:target) do
|
189
|
+
Person.new(title: 'Queen', age: 23)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "returns true" do
|
193
|
+
expect(matches).to be true
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'and model has identical values in all of the fields' do
|
198
|
+
let(:target) do
|
199
|
+
Person.new(title: 'Sir', age: 23)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "returns false" do
|
203
|
+
expect(matches).to be false
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|