search_object 1.0 → 1.1.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/.rubocop.yml +24 -0
- data/.travis.yml +4 -2
- data/CHANGELOG.md +40 -0
- data/README.md +38 -0
- data/example/Gemfile +2 -2
- data/example/app/assets/images/favicon.png +0 -0
- data/example/app/views/layouts/application.html.slim +1 -0
- data/example/config/environments/test.rb +1 -1
- data/example/screenshot.png +0 -0
- data/example/spec/models/post_search_spec.rb +11 -9
- data/example/spec/spec_helper.rb +1 -2
- data/lib/search_object/base.rb +22 -14
- data/lib/search_object/helper.rb +12 -4
- data/lib/search_object/plugin/kaminari.rb +0 -1
- data/lib/search_object/plugin/paging.rb +10 -10
- data/lib/search_object/plugin/sorting.rb +4 -4
- data/lib/search_object/search.rb +12 -0
- data/lib/search_object/version.rb +1 -1
- data/search_object.gemspec +2 -0
- data/spec/search_object/base_spec.rb +93 -57
- data/spec/search_object/helper_spec.rb +7 -7
- data/spec/search_object/plugin/kaminari_spec.rb +3 -3
- data/spec/search_object/plugin/model_spec.rb +6 -2
- data/spec/search_object/plugin/paging_spec.rb +1 -1
- data/spec/search_object/plugin/sorting_spec.rb +38 -33
- data/spec/search_object/plugin/will_paginate_spec.rb +3 -3
- data/spec/search_object/search_spec.rb +25 -26
- data/spec/spec_helper.rb +0 -1
- data/spec/spec_helper_active_record.rb +1 -1
- data/spec/support/kaminari_setup.rb +0 -1
- data/spec/support/paging_shared_example.rb +35 -32
- metadata +56 -27
@@ -3,18 +3,24 @@ require 'active_support/core_ext/object/blank'
|
|
3
3
|
|
4
4
|
module SearchObject
|
5
5
|
describe Base do
|
6
|
-
def
|
6
|
+
def define_search_class(&block)
|
7
7
|
Class.new do
|
8
8
|
include SearchObject.module
|
9
9
|
|
10
|
+
class_eval(&block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def search_class(default_scope = [], &block)
|
15
|
+
define_search_class do
|
10
16
|
scope { default_scope }
|
11
17
|
|
12
18
|
if block.nil?
|
13
19
|
option :value do |scope, value|
|
14
|
-
scope.
|
20
|
+
scope.select { |v| v == value }
|
15
21
|
end
|
16
22
|
else
|
17
|
-
class_eval
|
23
|
+
class_eval(&block)
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
@@ -23,22 +29,22 @@ module SearchObject
|
|
23
29
|
search_class(default_scope, &block).new filters: filters
|
24
30
|
end
|
25
31
|
|
26
|
-
it
|
32
|
+
it 'can had its #initialize method overwritten' do
|
27
33
|
search = new_search do
|
34
|
+
attr_reader :initialized
|
35
|
+
|
36
|
+
alias_method :initialized?, :initialized
|
37
|
+
|
28
38
|
def initialize(filters = {})
|
29
39
|
@initialized = true
|
30
40
|
super filters
|
31
41
|
end
|
32
|
-
|
33
|
-
def initialized?
|
34
|
-
@initialized
|
35
|
-
end
|
36
42
|
end
|
37
43
|
|
38
44
|
expect(search).to be_initialized
|
39
45
|
end
|
40
46
|
|
41
|
-
it
|
47
|
+
it 'can have multiple subclasses' do
|
42
48
|
search1 = new_search [1, 2, 3], filter: 1 do
|
43
49
|
option :filter do |scope, value|
|
44
50
|
scope.select { |v| v == value }
|
@@ -54,27 +60,43 @@ module SearchObject
|
|
54
60
|
expect(search1.results).not_to eq search2.results
|
55
61
|
end
|
56
62
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
63
|
+
it 'can be inherited' do
|
64
|
+
child_class = Class.new(search_class([1, 2, 3])) do
|
65
|
+
option :value do |scope, value|
|
66
|
+
scope.select { |v| v == value }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
expect(child_class.new(filters: { value: 1 }).results).to eq [1]
|
71
|
+
end
|
61
72
|
|
73
|
+
context 'scope' do
|
74
|
+
def search_class
|
75
|
+
define_search_class do
|
62
76
|
option :name do
|
63
77
|
end
|
64
78
|
end
|
65
79
|
end
|
66
80
|
|
67
|
-
it
|
81
|
+
it 'accepts scope as argument' do
|
68
82
|
expect(search_class.new(scope: 'scope').results).to eq 'scope'
|
69
83
|
end
|
70
84
|
|
71
|
-
it
|
72
|
-
expect { search_class.new }.to raise_error
|
85
|
+
it 'raises an error if scope is not provided' do
|
86
|
+
expect { search_class.new }.to raise_error MissingScopeError
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'can overwrite the search scope' do
|
90
|
+
search_class = define_search_class do
|
91
|
+
scope { 'scope' }
|
92
|
+
end
|
93
|
+
|
94
|
+
expect(search_class.new(scope: 'other scope').results).to eq 'other scope'
|
73
95
|
end
|
74
96
|
end
|
75
97
|
|
76
|
-
describe
|
77
|
-
it
|
98
|
+
describe 'option' do
|
99
|
+
it 'has default filter' do
|
78
100
|
scope = [1, 2, 3]
|
79
101
|
expect(scope).to receive(:where).with('value' => 1) { 'results' }
|
80
102
|
|
@@ -85,7 +107,7 @@ module SearchObject
|
|
85
107
|
expect(search.results).to eq 'results'
|
86
108
|
end
|
87
109
|
|
88
|
-
it
|
110
|
+
it 'returns the scope if nil returned' do
|
89
111
|
scope = [1, 2, 3]
|
90
112
|
search = new_search scope, value: 'some' do
|
91
113
|
option :value do
|
@@ -96,7 +118,7 @@ module SearchObject
|
|
96
118
|
expect(search.results).to eq scope
|
97
119
|
end
|
98
120
|
|
99
|
-
it
|
121
|
+
it 'can use methods from the object' do
|
100
122
|
search1 = new_search [1, 2, 3], filter: 1 do
|
101
123
|
option :filter do |scope, value|
|
102
124
|
some_instance_method(scope, value)
|
@@ -111,64 +133,78 @@ module SearchObject
|
|
111
133
|
|
112
134
|
expect(search1.results).to eq [1]
|
113
135
|
end
|
136
|
+
|
137
|
+
it 'can dispatch with instance methods' do
|
138
|
+
search = new_search [1, 2, 3], filter: 1 do
|
139
|
+
option :filter, with: :some_instance_method
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def some_instance_method(scope, value)
|
144
|
+
scope.select { |v| v == value }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
expect(search.results).to eq [1]
|
149
|
+
end
|
114
150
|
end
|
115
151
|
|
116
|
-
describe
|
117
|
-
it
|
152
|
+
describe 'option attributes' do
|
153
|
+
it 'access option values' do
|
118
154
|
search = new_search [], value: 1
|
119
155
|
expect(search.value).to eq 1
|
120
156
|
end
|
121
157
|
|
122
|
-
it
|
158
|
+
it 'returns default option value if option is not specified' do
|
123
159
|
search = new_search do
|
124
160
|
option :value, 1
|
125
161
|
end
|
126
162
|
expect(search.value).to eq 1
|
127
163
|
end
|
128
164
|
|
129
|
-
it
|
165
|
+
it 'does not include invalid options' do
|
130
166
|
search = new_search [], invalid: 'option'
|
131
167
|
expect { search.invalid }.to raise_error NoMethodError
|
132
168
|
end
|
133
169
|
end
|
134
170
|
|
135
|
-
describe
|
136
|
-
it
|
137
|
-
klass = search_class [1 ,
|
138
|
-
expect(klass.results(filters: {value: 1})).to eq [1]
|
171
|
+
describe '.results' do
|
172
|
+
it 'shortcut for creating new search and immediately returning results' do
|
173
|
+
klass = search_class [1, 2, 3]
|
174
|
+
expect(klass.results(filters: { value: 1 })).to eq [1]
|
139
175
|
end
|
140
176
|
end
|
141
177
|
|
142
|
-
describe
|
143
|
-
it
|
144
|
-
search = new_search [1 ,
|
178
|
+
describe '#results' do
|
179
|
+
it 'returns only the filtered search results' do
|
180
|
+
search = new_search [1, 2, 3], value: 1
|
145
181
|
expect(search.results).to eq [1]
|
146
182
|
end
|
147
183
|
|
148
|
-
it
|
149
|
-
|
150
|
-
search = new_search
|
184
|
+
it 'can apply several options' do
|
185
|
+
values = [1, 2, 3, 4, 5, 6, 7]
|
186
|
+
search = new_search values, bigger_than: 3, odd: true do
|
151
187
|
option :bigger_than do |scope, value|
|
152
|
-
scope.
|
188
|
+
scope.select { |v| v > value }
|
153
189
|
end
|
154
190
|
|
155
191
|
option :odd do |scope, value|
|
156
|
-
scope.
|
192
|
+
scope.select(&:odd?) if value
|
157
193
|
end
|
158
194
|
end
|
159
195
|
|
160
196
|
expect(search.results).to eq [5, 7]
|
161
197
|
end
|
162
198
|
|
163
|
-
it
|
199
|
+
it 'ignores invalid filters' do
|
164
200
|
search = new_search [1, 2, 3], invalid: 'option'
|
165
201
|
expect(search.results).to eq [1, 2, 3]
|
166
202
|
end
|
167
203
|
|
168
|
-
it
|
204
|
+
it 'can be overwritten by overwriting #fetch_results' do
|
169
205
|
search = new_search [1, 2, 3], value: 1 do
|
170
206
|
option :value do |scope, value|
|
171
|
-
scope.
|
207
|
+
scope.select { |v| v == value }
|
172
208
|
end
|
173
209
|
|
174
210
|
def fetch_results
|
@@ -179,8 +215,8 @@ module SearchObject
|
|
179
215
|
expect(search.results).to eq ['~1~']
|
180
216
|
end
|
181
217
|
|
182
|
-
it
|
183
|
-
search = new_search [1,2,3] do
|
218
|
+
it 'applies to default options' do
|
219
|
+
search = new_search [1, 2, 3] do
|
184
220
|
option :value, 1 do |scope, value|
|
185
221
|
scope.select { |v| v == value }
|
186
222
|
end
|
@@ -189,23 +225,23 @@ module SearchObject
|
|
189
225
|
end
|
190
226
|
end
|
191
227
|
|
192
|
-
describe
|
193
|
-
it
|
194
|
-
expect(new_search([1,2,3], value: 1).results?).to
|
228
|
+
describe '#results?' do
|
229
|
+
it 'returns true if there are results' do
|
230
|
+
expect(new_search([1, 2, 3], value: 1).results?).to be_truthy
|
195
231
|
end
|
196
232
|
|
197
|
-
it
|
198
|
-
expect(new_search([1,2,3], value: 4).results?).to
|
233
|
+
it 'returns false if there are no results' do
|
234
|
+
expect(new_search([1, 2, 3], value: 4).results?).to be_falsey
|
199
235
|
end
|
200
236
|
end
|
201
237
|
|
202
|
-
describe
|
203
|
-
it
|
204
|
-
expect(new_search([1,2,3], value: 1).count).to eq 1
|
238
|
+
describe '#count' do
|
239
|
+
it 'counts the number of results' do
|
240
|
+
expect(new_search([1, 2, 3], value: 1).count).to eq 1
|
205
241
|
end
|
206
242
|
|
207
|
-
it
|
208
|
-
search = new_search [1,2,3] do
|
243
|
+
it 'can not be bypassed by plugins' do
|
244
|
+
search = new_search [1, 2, 3] do
|
209
245
|
def fetch_results
|
210
246
|
[]
|
211
247
|
end
|
@@ -215,28 +251,28 @@ module SearchObject
|
|
215
251
|
end
|
216
252
|
end
|
217
253
|
|
218
|
-
describe
|
219
|
-
it
|
254
|
+
describe '#params' do
|
255
|
+
it 'exports options as params' do
|
220
256
|
search = new_search [], value: 1
|
221
257
|
expect(search.params).to eq 'value' => 1
|
222
258
|
end
|
223
259
|
|
224
|
-
it
|
260
|
+
it 'can overwrite options (mainly used for url handers)' do
|
225
261
|
search = new_search [], value: 1
|
226
262
|
expect(search.params(value: 2)).to eq 'value' => 2
|
227
263
|
end
|
228
264
|
|
229
|
-
it
|
265
|
+
it 'ignores missing options' do
|
230
266
|
search = new_search
|
231
267
|
expect(search.params).to eq({})
|
232
268
|
end
|
233
269
|
|
234
|
-
it
|
270
|
+
it 'ignores invalid options' do
|
235
271
|
search = new_search [], invalid: 'option'
|
236
272
|
expect(search.params).to eq({})
|
237
273
|
end
|
238
274
|
|
239
|
-
it
|
275
|
+
it 'includes default options' do
|
240
276
|
search = new_search do
|
241
277
|
option :value, 1
|
242
278
|
end
|
@@ -2,26 +2,26 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module SearchObject
|
4
4
|
describe Helper do
|
5
|
-
describe
|
6
|
-
it
|
5
|
+
describe '.stringify_keys' do
|
6
|
+
it 'converts hash keys to strings' do
|
7
7
|
hash = Helper.stringify_keys a: 1, b: nil, c: false
|
8
8
|
expect(hash).to eq 'a' => 1, 'b' => nil, 'c' => false
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
describe
|
13
|
-
it
|
14
|
-
hash = Helper.select_keys({a: 1, b: 2, c:3}, [:a, :b])
|
12
|
+
describe '.select_keys' do
|
13
|
+
it 'selects only given keys' do
|
14
|
+
hash = Helper.select_keys({ a: 1, b: 2, c: 3 }, [:a, :b])
|
15
15
|
expect(hash).to eq a: 1, b: 2
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
18
|
+
it 'ignores not existing keys' do
|
19
19
|
hash = Helper.select_keys({}, [:a, :b])
|
20
20
|
expect(hash).to eq({})
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
describe
|
24
|
+
describe 'camelize' do
|
25
25
|
it "transforms :paging to 'Paging'" do
|
26
26
|
expect(Helper.camelize(:paging)).to eq 'Paging'
|
27
27
|
end
|
@@ -5,10 +5,10 @@ require_relative '../../support/kaminari_setup'
|
|
5
5
|
module SearchObject
|
6
6
|
module Plugin
|
7
7
|
describe Kaminari do
|
8
|
-
it_behaves_like
|
9
|
-
it
|
8
|
+
it_behaves_like 'a paging plugin' do
|
9
|
+
it 'uses kaminari gem' do
|
10
10
|
search = search_with_page
|
11
|
-
expect(search.results.respond_to? :total_pages).to
|
11
|
+
expect(search.results.respond_to? :total_pages).to be_truthy
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -30,14 +30,18 @@ module SearchObject
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def assert(condition, message = nil)
|
33
|
-
expect(condition).to
|
33
|
+
expect(condition).to be_truthy, message
|
34
34
|
end
|
35
35
|
|
36
36
|
def assert_kind_of(expected_kind, object, message = nil)
|
37
37
|
expect(object).to be_kind_of(expected_kind), message
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
def assert_equal(expected_value, value, message = nil)
|
41
|
+
expect(value).to eq(expected_value), message
|
42
|
+
end
|
43
|
+
|
44
|
+
ActiveModel::Lint::Tests.public_instance_methods.map(&:to_s).grep(/^test/).each do |method|
|
41
45
|
example(method.gsub('_', ' ')) { send method }
|
42
46
|
end
|
43
47
|
end
|
@@ -17,123 +17,128 @@ module SearchObject
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def search_with_sort(sort = nil, filters = {})
|
20
|
-
search_class.new filters: {sort: sort}.merge(filters)
|
20
|
+
search_class.new filters: { sort: sort }.merge(filters)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
it 'can be inherited' do
|
24
|
+
child_class = Class.new(search_class)
|
25
|
+
expect(child_class.new.sort_attribute).to eq 'name'
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'sorting' do
|
24
29
|
after do
|
25
30
|
Product.delete_all
|
26
31
|
end
|
27
32
|
|
28
|
-
it
|
33
|
+
it 'sorts results based on the sort option' do
|
29
34
|
5.times { |i| Product.create! price: i }
|
30
35
|
|
31
36
|
search = search_with_sort 'price desc'
|
32
37
|
expect(search.results.map(&:price)).to eq [4, 3, 2, 1, 0]
|
33
38
|
end
|
34
39
|
|
35
|
-
it
|
40
|
+
it 'defaults to first sort by option' do
|
36
41
|
5.times { |i| Product.create! name: "Name#{i}" }
|
37
42
|
|
38
43
|
search = search_with_sort
|
39
44
|
expect(search.results.map(&:name)).to eq %w(Name4 Name3 Name2 Name1 Name0)
|
40
45
|
end
|
41
46
|
|
42
|
-
it
|
47
|
+
it 'ignores invalid sort values' do
|
43
48
|
search = search_with_sort 'invalid attribute'
|
44
49
|
expect { search.results.to_a }.not_to raise_error
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
|
-
describe
|
49
|
-
it
|
53
|
+
describe '#sort?' do
|
54
|
+
it 'matches the sort option' do
|
50
55
|
search = search_with_sort 'price desc'
|
51
56
|
|
52
|
-
expect(search.sort?(:price)).to
|
53
|
-
expect(search.sort?(:name)).to
|
57
|
+
expect(search.sort?(:price)).to be_truthy
|
58
|
+
expect(search.sort?(:name)).to be_falsey
|
54
59
|
end
|
55
60
|
|
56
|
-
it
|
61
|
+
it 'matches string also' do
|
57
62
|
search = search_with_sort 'price desc'
|
58
63
|
|
59
|
-
expect(search.sort?('price')).to
|
60
|
-
expect(search.sort?('name')).to
|
64
|
+
expect(search.sort?('price')).to be_truthy
|
65
|
+
expect(search.sort?('name')).to be_falsey
|
61
66
|
end
|
62
67
|
|
63
|
-
it
|
68
|
+
it 'matches exact strings' do
|
64
69
|
search = search_with_sort 'price desc'
|
65
70
|
|
66
|
-
expect(search.sort?('price desc')).to
|
67
|
-
expect(search.sort?('price asc')).to
|
71
|
+
expect(search.sort?('price desc')).to be_truthy
|
72
|
+
expect(search.sort?('price asc')).to be_falsey
|
68
73
|
end
|
69
74
|
end
|
70
75
|
|
71
|
-
describe
|
72
|
-
it
|
76
|
+
describe '#sort_attribute' do
|
77
|
+
it 'returns sort option attribute' do
|
73
78
|
search = search_with_sort 'price desc'
|
74
79
|
expect(search.sort_attribute).to eq 'price'
|
75
80
|
end
|
76
81
|
|
77
|
-
it
|
82
|
+
it 'defaults to the first sort by option' do
|
78
83
|
search = search_with_sort
|
79
84
|
expect(search.sort_attribute).to eq 'name'
|
80
85
|
end
|
81
86
|
|
82
|
-
it
|
87
|
+
it 'rejects invalid sort options, uses defaults' do
|
83
88
|
search = search_with_sort 'invalid'
|
84
89
|
expect(search.sort_attribute).to eq 'name'
|
85
90
|
end
|
86
91
|
end
|
87
92
|
|
88
|
-
describe
|
89
|
-
it
|
93
|
+
describe '#sort_direction' do
|
94
|
+
it 'returns asc or desc' do
|
90
95
|
expect(search_with_sort('price desc').sort_direction).to eq 'desc'
|
91
96
|
expect(search_with_sort('price asc').sort_direction).to eq 'asc'
|
92
97
|
end
|
93
98
|
|
94
|
-
it
|
99
|
+
it 'defaults to desc' do
|
95
100
|
expect(search_with_sort.sort_direction).to eq 'desc'
|
96
101
|
expect(search_with_sort('price').sort_direction).to eq 'desc'
|
97
102
|
end
|
98
103
|
|
99
|
-
it
|
104
|
+
it 'rejects invalid sort options, uses desc' do
|
100
105
|
expect(search_with_sort('price foo').sort_direction).to eq 'desc'
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
104
|
-
describe
|
105
|
-
it
|
109
|
+
describe '#sort_direction_for' do
|
110
|
+
it 'returns desc if current sort attribute is not the given attribute' do
|
106
111
|
expect(search_with_sort('price desc').sort_direction_for('name')).to eq 'desc'
|
107
112
|
end
|
108
113
|
|
109
|
-
it
|
114
|
+
it 'returns asc if current sort attribute is the given attribute' do
|
110
115
|
expect(search_with_sort('name desc').sort_direction_for('name')).to eq 'asc'
|
111
116
|
end
|
112
117
|
|
113
|
-
it
|
118
|
+
it 'returns desc if current sort attribute is the given attribute, but asc with direction' do
|
114
119
|
expect(search_with_sort('name asc').sort_direction_for('name')).to eq 'desc'
|
115
120
|
end
|
116
121
|
end
|
117
122
|
|
118
|
-
describe
|
119
|
-
it
|
123
|
+
describe '#sort_params_for' do
|
124
|
+
it 'adds sort direction' do
|
120
125
|
search = search_with_sort 'name', name: 'test'
|
121
126
|
expect(search.sort_params_for(:price)).to eq 'sort' => 'price desc', 'name' => 'test'
|
122
127
|
end
|
123
128
|
|
124
|
-
it
|
129
|
+
it 'reverses sort direction if this is the current sort attribute' do
|
125
130
|
search = search_with_sort 'name desc', name: 'test'
|
126
131
|
expect(search.sort_params_for(:name)).to eq 'sort' => 'name asc', 'name' => 'test'
|
127
132
|
end
|
128
133
|
|
129
|
-
it
|
134
|
+
it 'accepts additional options' do
|
130
135
|
search = search_with_sort
|
131
136
|
expect(search.sort_params_for(:price, name: 'value')).to eq 'sort' => 'price desc', 'name' => 'value'
|
132
137
|
end
|
133
138
|
end
|
134
139
|
|
135
|
-
describe
|
136
|
-
it
|
140
|
+
describe '#reverted_sort_direction' do
|
141
|
+
it 'reverts sorting direction' do
|
137
142
|
expect(search_with_sort('price desc').reverted_sort_direction).to eq 'asc'
|
138
143
|
expect(search_with_sort('price asc').reverted_sort_direction).to eq 'desc'
|
139
144
|
end
|
@@ -6,10 +6,10 @@ require 'will_paginate/active_record'
|
|
6
6
|
module SearchObject
|
7
7
|
module Plugin
|
8
8
|
describe WillPaginate do
|
9
|
-
it_behaves_like
|
10
|
-
it
|
9
|
+
it_behaves_like 'a paging plugin' do
|
10
|
+
it 'uses will_paginate gem' do
|
11
11
|
search = search_with_page
|
12
|
-
expect(search.results.respond_to? :total_entries).to
|
12
|
+
expect(search.results.respond_to? :total_entries).to be_truthy
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -2,69 +2,68 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module SearchObject
|
4
4
|
describe Search do
|
5
|
-
|
6
|
-
|
7
|
-
it "returns the passed params" do
|
5
|
+
describe '.params' do
|
6
|
+
it 'returns the passed params' do
|
8
7
|
search = Search.new('scope', 'params', {})
|
9
8
|
expect(search.params).to eq 'params'
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
13
|
-
describe
|
14
|
-
it
|
15
|
-
search = Search.new('scope', {name: 'value'}, {})
|
12
|
+
describe '.param' do
|
13
|
+
it 'returns the param value' do
|
14
|
+
search = Search.new('scope', { name: 'value' }, {})
|
16
15
|
expect(search.param(:name)).to eq 'value'
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
|
-
describe
|
21
|
-
it
|
19
|
+
describe '.query' do
|
20
|
+
it 'returns filtered result' do
|
22
21
|
actions = {
|
23
|
-
:
|
22
|
+
min: ->(scope, min) { scope.select { |v| v > min } }
|
24
23
|
}
|
25
24
|
|
26
|
-
search = Search.new [1,2,3], {min: 2}, actions
|
25
|
+
search = Search.new [1, 2, 3], { min: 2 }, actions
|
27
26
|
expect(search.query(Object.new)).to eq [3]
|
28
27
|
end
|
29
28
|
|
30
|
-
it
|
29
|
+
it 'applies actions to params' do
|
31
30
|
actions = {
|
32
|
-
:
|
33
|
-
:
|
31
|
+
min: ->(scope, min) { scope.select { |v| v > min } },
|
32
|
+
max: ->(scope, max) { scope.select { |v| v < max } }
|
34
33
|
}
|
35
34
|
|
36
|
-
search = Search.new [1,2,3,4,5], {min: 2, max: 5}, actions
|
37
|
-
expect(search.query(Object.new)).to eq [3,4]
|
35
|
+
search = Search.new [1, 2, 3, 4, 5], { min: 2, max: 5 }, actions
|
36
|
+
expect(search.query(Object.new)).to eq [3, 4]
|
38
37
|
end
|
39
38
|
|
40
|
-
it
|
39
|
+
it 'handles nil returned from action' do
|
41
40
|
actions = {
|
42
|
-
:
|
41
|
+
odd: ->(scope, odd) { scope.select(&:odd?) if odd }
|
43
42
|
}
|
44
43
|
|
45
|
-
search = Search.new [1,2,3,4,5], {odd: false}, actions
|
46
|
-
expect(search.query(Object.new)).to eq [1,2,3,4,5]
|
44
|
+
search = Search.new [1, 2, 3, 4, 5], { odd: false }, actions
|
45
|
+
expect(search.query(Object.new)).to eq [1, 2, 3, 4, 5]
|
47
46
|
end
|
48
47
|
|
49
|
-
it
|
48
|
+
it 'executes action in the passed context' do
|
50
49
|
actions = {
|
51
|
-
:
|
50
|
+
search: ->(scope, _) { scope.select { |v| v == target_value } }
|
52
51
|
}
|
53
52
|
|
54
53
|
context = double target_value: 2
|
55
54
|
|
56
|
-
search = Search.new [1,2,3,4,5], {search: true}, actions
|
55
|
+
search = Search.new [1, 2, 3, 4, 5], { search: true }, actions
|
57
56
|
expect(search.query(context)).to eq [2]
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
|
-
describe
|
62
|
-
it
|
60
|
+
describe '.count' do
|
61
|
+
it 'counts the results of the query' do
|
63
62
|
actions = {
|
64
|
-
:
|
63
|
+
value: ->(scope, value) { scope.select { |v| v == value } }
|
65
64
|
}
|
66
65
|
|
67
|
-
search = Search.new [1,2,3], {value: 2}, actions
|
66
|
+
search = Search.new [1, 2, 3], { value: 2 }, actions
|
68
67
|
expect(search.count(Object.new)).to eq 1
|
69
68
|
end
|
70
69
|
end
|
data/spec/spec_helper.rb
CHANGED