cuprum-collections 0.5.0 → 0.6.0.rc.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 +4 -4
- data/CHANGELOG.md +51 -0
- data/README.md +1 -1
- data/config/locales/en.rb +18 -0
- data/lib/cuprum/collections/adaptable/collection.rb +18 -0
- data/lib/cuprum/collections/adaptable/command.rb +22 -0
- data/lib/cuprum/collections/adaptable/commands/abstract_assign_one.rb +27 -0
- data/lib/cuprum/collections/adaptable/commands/abstract_build_one.rb +25 -0
- data/lib/cuprum/collections/adaptable/commands/abstract_validate_one.rb +35 -0
- data/lib/cuprum/collections/adaptable/commands.rb +15 -0
- data/lib/cuprum/collections/adaptable/query.rb +64 -0
- data/lib/cuprum/collections/adaptable.rb +13 -0
- data/lib/cuprum/collections/adapter.rb +300 -0
- data/lib/cuprum/collections/adapters/data_adapter.rb +82 -0
- data/lib/cuprum/collections/adapters/entity_adapter.rb +76 -0
- data/lib/cuprum/collections/adapters/hash_adapter.rb +48 -0
- data/lib/cuprum/collections/adapters.rb +14 -0
- data/lib/cuprum/collections/basic/collection.rb +2 -20
- data/lib/cuprum/collections/basic/commands/destroy_one.rb +1 -1
- data/lib/cuprum/collections/basic/commands/find_many.rb +0 -31
- data/lib/cuprum/collections/basic/commands/find_matching.rb +0 -94
- data/lib/cuprum/collections/basic/commands/find_one.rb +0 -18
- data/lib/cuprum/collections/basic/commands/insert_one.rb +1 -1
- data/lib/cuprum/collections/basic/commands/update_one.rb +1 -1
- data/lib/cuprum/collections/basic/scopes/criteria_scope.rb +36 -21
- data/lib/cuprum/collections/basic.rb +6 -5
- data/lib/cuprum/collections/collection.rb +6 -0
- data/lib/cuprum/collections/collection_command.rb +1 -1
- data/lib/cuprum/collections/commands/abstract_find_many.rb +40 -3
- data/lib/cuprum/collections/commands/abstract_find_matching.rb +102 -0
- data/lib/cuprum/collections/commands/abstract_find_one.rb +23 -1
- data/lib/cuprum/collections/commands/associations/find_many.rb +1 -3
- data/lib/cuprum/collections/commands/associations/require_many.rb +1 -1
- data/lib/cuprum/collections/commands/find_one_matching.rb +10 -10
- data/lib/cuprum/collections/commands/query_command.rb +6 -4
- data/lib/cuprum/collections/commands/upsert.rb +0 -2
- data/lib/cuprum/collections/constraints/order/attributes_array.rb +5 -4
- data/lib/cuprum/collections/constraints/order/attributes_hash.rb +5 -4
- data/lib/cuprum/collections/constraints/order/sort_direction.rb +2 -2
- data/lib/cuprum/collections/constraints/ordering.rb +11 -9
- data/lib/cuprum/collections/constraints/query_hash.rb +2 -2
- data/lib/cuprum/collections/errors/abstract_find_error.rb +101 -23
- data/lib/cuprum/collections/errors/extra_attributes.rb +3 -3
- data/lib/cuprum/collections/errors/failed_validation.rb +3 -3
- data/lib/cuprum/collections/errors/missing_default_contract.rb +12 -4
- data/lib/cuprum/collections/queries.rb +4 -0
- data/lib/cuprum/collections/relation.rb +0 -2
- data/lib/cuprum/collections/relations/parameters.rb +120 -68
- data/lib/cuprum/collections/repository.rb +71 -6
- data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +23 -4
- data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +18 -0
- data/lib/cuprum/collections/rspec/contracts/scope_contracts.rb +51 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/builder_contracts.rb +10 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/composition_contracts.rb +8 -0
- data/lib/cuprum/collections/rspec/contracts/scopes/criteria_contracts.rb +18 -366
- data/lib/cuprum/collections/rspec/contracts/scopes/logical_contracts.rb +30 -0
- data/lib/cuprum/collections/rspec/contracts/scopes.rb +2 -0
- data/lib/cuprum/collections/rspec/contracts.rb +2 -10
- data/lib/cuprum/collections/rspec/deferred/adapter_examples.rb +1077 -0
- data/lib/cuprum/collections/rspec/deferred/collection_examples.rb +27 -7
- data/lib/cuprum/collections/rspec/deferred/commands/assign_one_examples.rb +4 -4
- data/lib/cuprum/collections/rspec/deferred/commands/build_one_examples.rb +2 -2
- data/lib/cuprum/collections/rspec/deferred/commands/destroy_one_examples.rb +2 -2
- data/lib/cuprum/collections/rspec/deferred/commands/find_many_examples.rb +5 -5
- data/lib/cuprum/collections/rspec/deferred/commands/find_matching_examples.rb +45 -12
- data/lib/cuprum/collections/rspec/deferred/commands/find_one_examples.rb +2 -2
- data/lib/cuprum/collections/rspec/deferred/commands/insert_one_examples.rb +1 -1
- data/lib/cuprum/collections/rspec/deferred/commands/update_one_examples.rb +1 -1
- data/lib/cuprum/collections/rspec/deferred/query_examples.rb +930 -0
- data/lib/cuprum/collections/rspec/deferred/relation_examples.rb +48 -17
- data/lib/cuprum/collections/rspec/deferred/repository_examples.rb +961 -0
- data/lib/cuprum/collections/rspec/deferred/scope_examples.rb +598 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/all_examples.rb +391 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/builder_examples.rb +857 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/composition_examples.rb +93 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/conjunction_examples.rb +438 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/criteria_examples.rb +1941 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/disjunction_examples.rb +415 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/none_examples.rb +385 -0
- data/lib/cuprum/collections/rspec/deferred/scopes/parser_examples.rb +740 -0
- data/lib/cuprum/collections/rspec/deferred/scopes.rb +8 -0
- data/lib/cuprum/collections/scope.rb +2 -2
- data/lib/cuprum/collections/scopes/container.rb +5 -4
- data/lib/cuprum/collections/scopes/criteria/parser.rb +24 -48
- data/lib/cuprum/collections/scopes/criteria.rb +7 -6
- data/lib/cuprum/collections/version.rb +3 -3
- data/lib/cuprum/collections.rb +5 -1
- metadata +48 -11
- data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +0 -2127
- data/lib/cuprum/collections/rspec/contracts/basic.rb +0 -11
- data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +0 -387
- data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +0 -169
- data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +0 -1264
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/sleeping_king_studios/deferred'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/collections/rspec/deferred/scopes'
|
|
6
|
+
|
|
7
|
+
module Cuprum::Collections::RSpec::Deferred::Scopes
|
|
8
|
+
# Deferred examples for asserting on scope composition.
|
|
9
|
+
module CompositionExamples
|
|
10
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
|
11
|
+
|
|
12
|
+
deferred_context 'with contexts for composable scopes' do
|
|
13
|
+
deferred_context 'with an all scope' do
|
|
14
|
+
let(:original) do
|
|
15
|
+
Cuprum::Collections::Scopes::AllScope.new
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
deferred_context 'with a none scope' do
|
|
20
|
+
let(:original) do
|
|
21
|
+
Cuprum::Collections::Scopes::NoneScope.new
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
deferred_context 'with an empty conjunction scope' do
|
|
26
|
+
let(:original) do
|
|
27
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(scopes: [])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
deferred_context 'with an empty criteria scope' do
|
|
32
|
+
let(:original) do
|
|
33
|
+
Cuprum::Collections::Scopes::CriteriaScope.new(criteria: [])
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
deferred_context 'with an empty disjunction scope' do
|
|
38
|
+
let(:original) do
|
|
39
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(scopes: [])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
deferred_context 'with a non-empty conjunction scope' do
|
|
44
|
+
let(:original) do
|
|
45
|
+
operators = Cuprum::Collections::Queries::Operators
|
|
46
|
+
criteria = [
|
|
47
|
+
[
|
|
48
|
+
'category',
|
|
49
|
+
operators::EQUAL,
|
|
50
|
+
'Science Fiction and Fantasy'
|
|
51
|
+
]
|
|
52
|
+
]
|
|
53
|
+
wrapped =
|
|
54
|
+
Cuprum::Collections::Scopes::CriteriaScope.new(criteria:)
|
|
55
|
+
|
|
56
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(scopes: [wrapped])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
deferred_context 'with a non-empty criteria scope' do
|
|
61
|
+
let(:original) do
|
|
62
|
+
operators = Cuprum::Collections::Queries::Operators
|
|
63
|
+
criteria = [
|
|
64
|
+
[
|
|
65
|
+
'category',
|
|
66
|
+
operators::EQUAL,
|
|
67
|
+
'Science Fiction and Fantasy'
|
|
68
|
+
]
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
Cuprum::Collections::Scopes::CriteriaScope.new(criteria:)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
deferred_context 'with a non-empty disjunction scope' do
|
|
76
|
+
let(:original) do
|
|
77
|
+
operators = Cuprum::Collections::Queries::Operators
|
|
78
|
+
criteria = [
|
|
79
|
+
[
|
|
80
|
+
'category',
|
|
81
|
+
operators::EQUAL,
|
|
82
|
+
'Science Fiction and Fantasy'
|
|
83
|
+
]
|
|
84
|
+
]
|
|
85
|
+
wrapped =
|
|
86
|
+
Cuprum::Collections::Scopes::CriteriaScope.new(criteria:)
|
|
87
|
+
|
|
88
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(scopes: [wrapped])
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/sleeping_king_studios/deferred'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/collections/rspec/deferred/scope_examples'
|
|
6
|
+
require 'cuprum/collections/rspec/deferred/scopes'
|
|
7
|
+
require 'cuprum/collections/rspec/deferred/scopes/composition_examples'
|
|
8
|
+
|
|
9
|
+
module Cuprum::Collections::RSpec::Deferred::Scopes
|
|
10
|
+
# Deferred examples for asserting on Conjunction scope objects.
|
|
11
|
+
module ConjunctionExamples
|
|
12
|
+
include RSpec::SleepingKingStudios::Deferred::Provider
|
|
13
|
+
include Cuprum::Collections::RSpec::Deferred::ScopeExamples
|
|
14
|
+
include Cuprum::Collections::RSpec::Deferred::Scopes::CompositionExamples
|
|
15
|
+
|
|
16
|
+
deferred_examples 'should implement the ConjunctionScope methods' \
|
|
17
|
+
do |**deferred_options|
|
|
18
|
+
deferred_context 'when the scope has many child scopes' do
|
|
19
|
+
let(:scopes) do
|
|
20
|
+
[
|
|
21
|
+
build_scope({ 'author' => 'J.R.R. Tolkien' }),
|
|
22
|
+
build_scope({ 'series' => 'The Lord of the Rings' }),
|
|
23
|
+
build_scope do |scope|
|
|
24
|
+
{ 'published_at' => scope.less_than('1955-01-01') }
|
|
25
|
+
end
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
include_deferred 'should implement the Scope methods'
|
|
31
|
+
|
|
32
|
+
include_deferred 'should define child scopes'
|
|
33
|
+
|
|
34
|
+
include_deferred 'should compose Scopes as a ConjunctionScope'
|
|
35
|
+
|
|
36
|
+
describe '#as_json' do
|
|
37
|
+
let(:expected) do
|
|
38
|
+
{
|
|
39
|
+
'scopes' => subject.scopes.map(&:as_json),
|
|
40
|
+
'type' => subject.type
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it { expect(subject.as_json).to be == expected }
|
|
45
|
+
|
|
46
|
+
wrap_deferred 'with scopes' do
|
|
47
|
+
it { expect(subject.as_json).to be == expected }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#call' do
|
|
52
|
+
next if deferred_options.fetch(:abstract, false)
|
|
53
|
+
|
|
54
|
+
include_deferred 'should filter data by logical AND'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#invert' do
|
|
58
|
+
let(:expected) do
|
|
59
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
60
|
+
scopes: subject.scopes.map(&:invert)
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it { expect(subject.invert).to be == expected }
|
|
65
|
+
|
|
66
|
+
wrap_deferred 'with scopes' do
|
|
67
|
+
it { expect(subject.invert).to be == expected }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#type' do
|
|
72
|
+
include_examples 'should define reader', :type, :conjunction
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
deferred_examples 'should compose Scopes as a ConjunctionScope' do
|
|
77
|
+
describe '#and' do
|
|
78
|
+
include_deferred 'with contexts for composable scopes'
|
|
79
|
+
|
|
80
|
+
describe 'with a block' do
|
|
81
|
+
let(:block) { -> { { 'title' => 'A Wizard of Earthsea' } } }
|
|
82
|
+
let(:expected) do
|
|
83
|
+
wrapped = Cuprum::Collections::Scope.new(&block)
|
|
84
|
+
|
|
85
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
86
|
+
scopes: [*subject.scopes, wrapped]
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it { expect(subject.and(&block)).to be == expected }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe 'with a hash' do
|
|
94
|
+
let(:value) { { 'title' => 'A Wizard of Earthsea' } }
|
|
95
|
+
let(:expected) do
|
|
96
|
+
wrapped = Cuprum::Collections::Scope.new(value)
|
|
97
|
+
|
|
98
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
99
|
+
scopes: [*subject.scopes, wrapped]
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it { expect(subject.and(value)).to be == expected }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
wrap_deferred 'with an all scope' do
|
|
107
|
+
it { expect(subject.and(original)).to be subject }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
wrap_deferred 'with a none scope' do
|
|
111
|
+
it { expect(subject.and(original)).to be == original }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
wrap_deferred 'with an empty conjunction scope' do
|
|
115
|
+
it { expect(subject.and(original)).to be subject }
|
|
116
|
+
|
|
117
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
118
|
+
it { expect(subject.and(original)).to be subject }
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
wrap_deferred 'with an empty criteria scope' do
|
|
123
|
+
it { expect(subject.and(original)).to be subject }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
wrap_deferred 'with an empty disjunction scope' do
|
|
127
|
+
it { expect(subject.and(original)).to be subject }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
wrap_deferred 'with a non-empty conjunction scope' do
|
|
131
|
+
let(:expected) do
|
|
132
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
133
|
+
scopes: [*subject.scopes, *original.scopes]
|
|
134
|
+
)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it { expect(subject.and(original)).to be == expected }
|
|
138
|
+
|
|
139
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
140
|
+
it { expect(subject.and(original)).to be == expected }
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
wrap_deferred 'with a non-empty criteria scope' do
|
|
145
|
+
let(:expected) do
|
|
146
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
147
|
+
scopes: [*subject.scopes, original]
|
|
148
|
+
)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it { expect(subject.and(original)).to be == expected }
|
|
152
|
+
|
|
153
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
154
|
+
it { expect(subject.and(original)).to be == expected }
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
wrap_deferred 'with a non-empty disjunction scope' do
|
|
159
|
+
let(:expected) do
|
|
160
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
161
|
+
scopes: [*subject.scopes, original]
|
|
162
|
+
)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it { expect(subject.and(original)).to be == expected }
|
|
166
|
+
|
|
167
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
168
|
+
it { expect(subject.and(original)).to be == expected }
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe '#not' do
|
|
174
|
+
include_deferred 'with contexts for composable scopes'
|
|
175
|
+
|
|
176
|
+
describe 'with a block' do
|
|
177
|
+
let(:block) { -> { { 'title' => 'A Wizard of Earthsea' } } }
|
|
178
|
+
let(:expected) do
|
|
179
|
+
wrapped = Cuprum::Collections::Scope.new(&block)
|
|
180
|
+
|
|
181
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
182
|
+
scopes: [*subject.scopes, wrapped.invert]
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it { expect(subject.not(&block)).to be == expected }
|
|
187
|
+
|
|
188
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
189
|
+
it { expect(subject.not(&block)).to be == expected }
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe 'with a hash' do
|
|
194
|
+
let(:value) { { 'title' => 'A Wizard of Earthsea' } }
|
|
195
|
+
let(:expected) do
|
|
196
|
+
wrapped = Cuprum::Collections::Scope.new(value)
|
|
197
|
+
|
|
198
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
199
|
+
scopes: [*subject.scopes, wrapped.invert]
|
|
200
|
+
)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it { expect(subject.not(value)).to be == expected }
|
|
204
|
+
|
|
205
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
206
|
+
it { expect(subject.not(value)).to be == expected }
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
wrap_deferred 'with an all scope' do
|
|
211
|
+
let(:expected) { Cuprum::Collections::Scopes::NoneScope.new }
|
|
212
|
+
|
|
213
|
+
it { expect(subject.not(original)).to be == expected }
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
wrap_deferred 'with a none scope' do
|
|
217
|
+
it { expect(subject.not(original)).to be subject }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
wrap_deferred 'with an empty conjunction scope' do
|
|
221
|
+
it { expect(subject.not(original)).to be subject }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
wrap_deferred 'with an empty criteria scope' do
|
|
225
|
+
it { expect(subject.not(original)).to be subject }
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
wrap_deferred 'with an empty disjunction scope' do
|
|
229
|
+
it { expect(subject.not(original)).to be subject }
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
wrap_deferred 'with a non-empty conjunction scope' do
|
|
233
|
+
let(:expected) do
|
|
234
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
235
|
+
scopes: [*subject.scopes, original.invert]
|
|
236
|
+
)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it { expect(subject.not(original)).to be == expected }
|
|
240
|
+
|
|
241
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
242
|
+
it { expect(subject.not(original)).to be == expected }
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
wrap_deferred 'with a non-empty criteria scope' do
|
|
247
|
+
let(:expected) do
|
|
248
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
249
|
+
scopes: [*subject.scopes, original.invert]
|
|
250
|
+
)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it { expect(subject.not(original)).to be == expected }
|
|
254
|
+
|
|
255
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
256
|
+
it { expect(subject.not(original)).to be == expected }
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
wrap_deferred 'with a non-empty disjunction scope' do
|
|
261
|
+
let(:expected) do
|
|
262
|
+
Cuprum::Collections::Scopes::ConjunctionScope.new(
|
|
263
|
+
scopes: [*subject.scopes, *original.invert.scopes]
|
|
264
|
+
)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it { expect(subject.not(original)).to be == expected }
|
|
268
|
+
|
|
269
|
+
wrap_deferred 'when the scope has many child scopes' do
|
|
270
|
+
it { expect(subject.not(original)).to be == expected }
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
describe '#or' do
|
|
276
|
+
include_deferred 'with contexts for composable scopes'
|
|
277
|
+
|
|
278
|
+
it 'should define the method' do
|
|
279
|
+
expect(subject)
|
|
280
|
+
.to respond_to(:or)
|
|
281
|
+
.with(0..1).arguments
|
|
282
|
+
.and_a_block
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
describe 'with a block' do
|
|
286
|
+
let(:block) { -> { { 'title' => 'A Wizard of Earthsea' } } }
|
|
287
|
+
let(:expected) do
|
|
288
|
+
wrapped = Cuprum::Collections::Scope.new(&block)
|
|
289
|
+
|
|
290
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
291
|
+
scopes: [subject, wrapped]
|
|
292
|
+
)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it { expect(subject.or(&block)).to be == expected }
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
describe 'with a hash' do
|
|
299
|
+
let(:value) { { 'title' => 'A Wizard of Earthsea' } }
|
|
300
|
+
let(:expected) do
|
|
301
|
+
wrapped = Cuprum::Collections::Scope.new(value)
|
|
302
|
+
|
|
303
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
304
|
+
scopes: [subject, wrapped]
|
|
305
|
+
)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it { expect(subject.or(value)).to be == expected }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
wrap_deferred 'with an all scope' do
|
|
312
|
+
it { expect(subject.or(original)).to be == original }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
wrap_deferred 'with a none scope' do
|
|
316
|
+
it { expect(subject.or(original)).to be subject }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
wrap_deferred 'with an empty conjunction scope' do
|
|
320
|
+
it { expect(subject.or(original)).to be subject }
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
wrap_deferred 'with an empty criteria scope' do
|
|
324
|
+
it { expect(subject.or(original)).to be subject }
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
wrap_deferred 'with an empty disjunction scope' do
|
|
328
|
+
it { expect(subject.or(original)).to be subject }
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
wrap_deferred 'with a non-empty conjunction scope' do
|
|
332
|
+
let(:expected) do
|
|
333
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
334
|
+
scopes: [subject, original]
|
|
335
|
+
)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it { expect(subject.or(original)).to be == expected }
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
wrap_deferred 'with a non-empty criteria scope' do
|
|
342
|
+
let(:expected) do
|
|
343
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
344
|
+
scopes: [subject, original]
|
|
345
|
+
)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it { expect(subject.or(original)).to be == expected }
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
wrap_deferred 'with a non-empty disjunction scope' do
|
|
352
|
+
let(:expected) do
|
|
353
|
+
Cuprum::Collections::Scopes::DisjunctionScope.new(
|
|
354
|
+
scopes: [subject, *original.scopes]
|
|
355
|
+
)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
it { expect(subject.or(original)).to be == expected }
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
deferred_examples 'should filter data by logical AND' do
|
|
364
|
+
deferred_context 'with data' do
|
|
365
|
+
let(:data) do
|
|
366
|
+
Cuprum::Collections::RSpec::Fixtures::BOOKS_FIXTURES
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context 'when the scope has no child scopes' do
|
|
371
|
+
let(:scopes) { [] }
|
|
372
|
+
|
|
373
|
+
describe 'with empty data' do
|
|
374
|
+
let(:data) { [] }
|
|
375
|
+
|
|
376
|
+
it { expect(filtered_data).to be == [] }
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
wrap_deferred 'with data' do
|
|
380
|
+
let(:expected) { data }
|
|
381
|
+
|
|
382
|
+
it { expect(filtered_data).to match_array expected }
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
context 'when the scope has one child scope' do
|
|
387
|
+
let(:scopes) do
|
|
388
|
+
[
|
|
389
|
+
build_scope({ 'author' => 'J.R.R. Tolkien' })
|
|
390
|
+
]
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
describe 'with empty data' do
|
|
394
|
+
let(:data) { [] }
|
|
395
|
+
|
|
396
|
+
it { expect(filtered_data).to be == [] }
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
wrap_deferred 'with data' do
|
|
400
|
+
let(:expected) do
|
|
401
|
+
data.select { |item| item['author'] == 'J.R.R. Tolkien' }
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
it { expect(filtered_data).to match_array expected }
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
context 'when the scope has many child scopes' do
|
|
409
|
+
let(:scopes) do
|
|
410
|
+
[
|
|
411
|
+
build_scope({ 'author' => 'J.R.R. Tolkien' }),
|
|
412
|
+
build_scope({ 'series' => 'The Lord of the Rings' }),
|
|
413
|
+
build_scope do |scope|
|
|
414
|
+
{ 'published_at' => scope.less_than('1955-01-01') }
|
|
415
|
+
end
|
|
416
|
+
]
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
describe 'with empty data' do
|
|
420
|
+
let(:data) { [] }
|
|
421
|
+
|
|
422
|
+
it { expect(filtered_data).to be == [] }
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
wrap_deferred 'with data' do
|
|
426
|
+
let(:expected) do
|
|
427
|
+
data
|
|
428
|
+
.select { |item| item['author'] == 'J.R.R. Tolkien' }
|
|
429
|
+
.select { |item| item['series'] == 'The Lord of the Rings' }
|
|
430
|
+
.select { |item| item['published_at'] < '1955-01-01' }
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it { expect(filtered_data).to match_array expected }
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
end
|