active_record_filterable 0.1.0 → 1.0.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/README.md +12 -13
- data/active_record_filterable.gemspec +0 -1
- data/lib/active_record_filterable.rb +0 -3
- data/lib/active_record_filterable/filterable.rb +30 -1
- data/lib/active_record_filterable/version.rb +1 -1
- data/spec/filterable_spec.rb +22 -22
- metadata +3 -19
- data/lib/active_record_filterable/filter.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f3fd07975c6a48200e596542644ddad458e3ff3293bee739151f4d25eae5231
|
4
|
+
data.tar.gz: c9415f4f77e93081d2189f9891709d3a009e98fc01c613ca6c059363f5f581b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13c55dec18594a7ec978776e58ad25c0613e29d1258f68fd209ebcc2687fe46ff2981b240d29e2544db6819ad02dc85a5fc8c43324c6d3ffa29fd43ee19725d9
|
7
|
+
data.tar.gz: 42a9dc6a30c48bb94473ab9f9685944e0bbc65367806a7b5bdd97a703bb4536c3d873147f31308bc0e5d51301cfe8272812a1495098c8686ba49b77ae846d6c8
|
data/README.md
CHANGED
@@ -29,19 +29,18 @@ class City < ActiveRecord::Base
|
|
29
29
|
field :people
|
30
30
|
|
31
31
|
filter_by(:name)
|
32
|
-
filter_by(:people, ->(value) { where(:people.gt
|
32
|
+
filter_by(:people, ->(value) { where(City.arel_table[:people].gt(value)) })
|
33
33
|
filter_by(:people_range, (lambda do |range_start, range_end|
|
34
|
-
where(:
|
35
|
-
:people.gte => range_start)
|
34
|
+
where(people: range_start..range_end)
|
36
35
|
end))
|
37
36
|
end
|
38
37
|
|
39
38
|
City.create(name: 'city1', people: 100)
|
40
39
|
City.create(name: 'city2', people: 1000)
|
41
|
-
City.
|
42
|
-
City.
|
43
|
-
City.
|
44
|
-
City.
|
40
|
+
City.filtrate({name: 'city'}).count # => 2
|
41
|
+
City.filtrate({name: 'city1'}).count # => 1
|
42
|
+
City.filtrate({name: ''}).count # => 0
|
43
|
+
City.filtrate({people: 500}) # => 1
|
45
44
|
```
|
46
45
|
|
47
46
|
#### Operator
|
@@ -52,8 +51,8 @@ You can specify selector operator:
|
|
52
51
|
* or
|
53
52
|
|
54
53
|
```ruby
|
55
|
-
City.
|
56
|
-
City.
|
54
|
+
City.filtrate({name: 'city1', people: 1000}, 'and').count # => 0
|
55
|
+
City.filtrate({name: 'city1', people: 1000}, 'or').count # => 1
|
57
56
|
```
|
58
57
|
|
59
58
|
#### Range
|
@@ -61,7 +60,7 @@ City.filter({name: 'city1', people: 1000}, 'or').count # => 1
|
|
61
60
|
Searches with more than one param is also available:
|
62
61
|
|
63
62
|
```ruby
|
64
|
-
City.
|
63
|
+
City.filtrate(people_range: [500, 1000]).count # => 1
|
65
64
|
```
|
66
65
|
|
67
66
|
#### Rails controller
|
@@ -69,7 +68,7 @@ City.filter(people_range: [500, 1000]).count # => 1
|
|
69
68
|
```ruby
|
70
69
|
class CitiesController
|
71
70
|
def index
|
72
|
-
respond_with City.
|
71
|
+
respond_with City.filtrate(filter_params)
|
73
72
|
end
|
74
73
|
|
75
74
|
private
|
@@ -82,7 +81,7 @@ end
|
|
82
81
|
|
83
82
|
#### Normalized values
|
84
83
|
|
85
|
-
Searches without considering accents are also supported.
|
84
|
+
Searches without considering accents are also supported.
|
86
85
|
|
87
86
|
```ruby
|
88
87
|
filter_by_normalized :name
|
@@ -90,7 +89,7 @@ Searches without considering accents are also supported.
|
|
90
89
|
enables to do sth like:
|
91
90
|
|
92
91
|
```ruby
|
93
|
-
City.
|
92
|
+
City.filtrate(name_normalized: 'text with accents')
|
94
93
|
```
|
95
94
|
|
96
95
|
It also depends on which adapter you are using.
|
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
21
|
spec.add_development_dependency 'rspec'
|
23
22
|
spec.add_development_dependency 'pry-byebug'
|
24
23
|
spec.add_development_dependency 'sqlite3'
|
@@ -9,7 +9,36 @@ module ActiveRecord
|
|
9
9
|
|
10
10
|
# rubocop:disable Metrics/BlockLength
|
11
11
|
class_methods do
|
12
|
-
|
12
|
+
##
|
13
|
+
# Applies params scopes to current scope
|
14
|
+
#
|
15
|
+
def filtrate(filtering_params, operator='and')
|
16
|
+
return all if filtering_params.blank?
|
17
|
+
criteria = nil
|
18
|
+
|
19
|
+
unscoped do
|
20
|
+
criteria = is_a?(ActiveRecord::Relation) ? self : all
|
21
|
+
|
22
|
+
filtering_params.each do |key, value|
|
23
|
+
next unless respond_to?("filter_with_#{key}")
|
24
|
+
|
25
|
+
# Add support for both kind of scopes: scope with multiple arguments and scope with
|
26
|
+
# one argument as array
|
27
|
+
value = [value] unless value.is_a?(Array) &&
|
28
|
+
scope_arities["filter_with_#{key}".to_sym] > 1
|
29
|
+
|
30
|
+
# check the number of arguments of filter scope
|
31
|
+
criteria =
|
32
|
+
if operator == 'and' || criteria.where_clause.empty?
|
33
|
+
criteria.public_send("filter_with_#{key}", *value)
|
34
|
+
else
|
35
|
+
criteria.or(all.public_send("filter_with_#{key}", *value))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
criteria == self ? none : merge(criteria)
|
41
|
+
end
|
13
42
|
|
14
43
|
def scope(name, scope_options, &block)
|
15
44
|
super
|
data/spec/filterable_spec.rb
CHANGED
@@ -30,12 +30,12 @@ RSpec.describe ActiveRecord::Filterable do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'filters' do
|
33
|
-
expect(City.
|
34
|
-
expect(City.
|
33
|
+
expect(City.filtrate(code: :code1).count).to eq(1)
|
34
|
+
expect(City.filtrate(code: :code1).first.code).to eq('code1')
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'doesn\'t find anything with partial match' do
|
38
|
-
expect(City.
|
38
|
+
expect(City.filtrate(name: :city).count).to eq(0)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -47,11 +47,11 @@ RSpec.describe ActiveRecord::Filterable do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'respects default_scope' do
|
50
|
-
expect(City.
|
50
|
+
expect(City.filtrate(nil).count).to eq(2)
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'ignores filter' do
|
54
|
-
expect(City.
|
54
|
+
expect(City.filtrate(nil).count).to eq(2)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -63,11 +63,11 @@ RSpec.describe ActiveRecord::Filterable do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'should respect default_scope' do
|
66
|
-
expect(City.
|
66
|
+
expect(City.filtrate(invalid: 'val').count).to eq(2)
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'should ignore filter' do
|
70
|
-
expect(City.
|
70
|
+
expect(City.filtrate(invalid: 'val').count).to eq(2)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -81,11 +81,11 @@ RSpec.describe ActiveRecord::Filterable do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'receives all the values' do
|
84
|
-
expect(City.
|
84
|
+
expect(City.filtrate(people_range: [500, 1000]).count).to eq(3)
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'does not break compatibility with filters receiving only one param as array' do
|
88
|
-
expect(City.
|
88
|
+
expect(City.filtrate(people_in: [500, 100]).count).to eq(2)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -96,7 +96,7 @@ RSpec.describe ActiveRecord::Filterable do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'applies filter' do
|
99
|
-
expect(City.
|
99
|
+
expect(City.filtrate(people: '').count).to eq(0)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -107,7 +107,7 @@ RSpec.describe ActiveRecord::Filterable do
|
|
107
107
|
end
|
108
108
|
|
109
109
|
it 'filters using a query' do
|
110
|
-
expect(City.unscoped.
|
110
|
+
expect(City.unscoped.filtrate(active: false).count).to eq(1)
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -118,8 +118,8 @@ RSpec.describe ActiveRecord::Filterable do
|
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'filters' do
|
121
|
-
expect(City.
|
122
|
-
expect(City.
|
121
|
+
expect(City.filtrate(people: 500).count).to eq(1)
|
122
|
+
expect(City.filtrate(people: 500).first.people).to eq(1000)
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -132,16 +132,16 @@ RSpec.describe ActiveRecord::Filterable do
|
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'filters ignoring upcase' do
|
135
|
-
expect(City.
|
136
|
-
expect(City.
|
135
|
+
expect(City.filtrate(name_normalized: 'spain').first.name).to eq('spaIn')
|
136
|
+
expect(City.filtrate(name_normalized: 'france').first.name).to eq('frAnce')
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'filters ignoring special characters', sqlite: false do
|
140
|
-
expect(City.
|
140
|
+
expect(City.filtrate(name_normalized: '%').first.name).to eq('_russian%')
|
141
141
|
end
|
142
142
|
|
143
143
|
it 'filters ignoring accents', sqlite: false do
|
144
|
-
expect(City.
|
144
|
+
expect(City.filtrate(name_normalized: 'italy').first.name).to eq('itály')
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -154,7 +154,7 @@ RSpec.describe ActiveRecord::Filterable do
|
|
154
154
|
end
|
155
155
|
|
156
156
|
it 'is maintained' do
|
157
|
-
expect(City.where(name: '2').
|
157
|
+
expect(City.where(name: '2').filtrate(nil).count).to eq(1)
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
@@ -166,8 +166,8 @@ RSpec.describe ActiveRecord::Filterable do
|
|
166
166
|
end
|
167
167
|
|
168
168
|
it 'respects previous selector' do
|
169
|
-
expect(City.where(name: 'city2').
|
170
|
-
expect(City.where(name: 'city2').
|
169
|
+
expect(City.where(name: 'city2').filtrate(people: '500').count).to eq(1)
|
170
|
+
expect(City.where(name: 'city2').filtrate(people: '500').first.name).to eq('city2')
|
171
171
|
end
|
172
172
|
end
|
173
173
|
end
|
@@ -179,7 +179,7 @@ RSpec.describe ActiveRecord::Filterable do
|
|
179
179
|
end
|
180
180
|
|
181
181
|
it 'filters' do
|
182
|
-
expect(City.
|
182
|
+
expect(City.filtrate({name: 'city1', people: '2000'}, 'and').count).to eq(0)
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
@@ -190,7 +190,7 @@ RSpec.describe ActiveRecord::Filterable do
|
|
190
190
|
end
|
191
191
|
|
192
192
|
it 'filters' do
|
193
|
-
expect(City.
|
193
|
+
expect(City.filtrate({name: 'city1', people: 500}, 'or').count).to eq(2)
|
194
194
|
end
|
195
195
|
end
|
196
196
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_filterable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francisco Padillo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.5'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.5'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rspec
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,7 +107,6 @@ files:
|
|
121
107
|
- Rakefile
|
122
108
|
- active_record_filterable.gemspec
|
123
109
|
- lib/active_record_filterable.rb
|
124
|
-
- lib/active_record_filterable/filter.rb
|
125
110
|
- lib/active_record_filterable/filterable.rb
|
126
111
|
- lib/active_record_filterable/version.rb
|
127
112
|
- spec/filterable_spec.rb
|
@@ -148,8 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
133
|
- !ruby/object:Gem::Version
|
149
134
|
version: '0'
|
150
135
|
requirements: []
|
151
|
-
|
152
|
-
rubygems_version: 2.7.3
|
136
|
+
rubygems_version: 3.0.1
|
153
137
|
signing_key:
|
154
138
|
specification_version: 4
|
155
139
|
summary: Easy way to add scopes to your models.
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Filterable
|
3
|
-
module Filter
|
4
|
-
##
|
5
|
-
# Applies params scopes to current scope
|
6
|
-
#
|
7
|
-
def filter(filtering_params, operator='and')
|
8
|
-
return all if filtering_params.blank?
|
9
|
-
criteria = nil
|
10
|
-
|
11
|
-
unscoped do
|
12
|
-
criteria = is_a?(ActiveRecord::Relation) ? self : all
|
13
|
-
|
14
|
-
filtering_params.each do |key, value|
|
15
|
-
next unless respond_to?("filter_with_#{key}")
|
16
|
-
|
17
|
-
# Add support for both kind of scopes: scope with multiple arguments and scope with
|
18
|
-
# one argument as array
|
19
|
-
value = [value] unless value.is_a?(Array) &&
|
20
|
-
scope_arities["filter_with_#{key}".to_sym] > 1
|
21
|
-
|
22
|
-
# check the number of arguments of filter scope
|
23
|
-
criteria =
|
24
|
-
if operator == 'and' || criteria.where_clause.empty?
|
25
|
-
criteria.public_send("filter_with_#{key}", *value)
|
26
|
-
else
|
27
|
-
criteria.or(all.public_send("filter_with_#{key}", *value))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
criteria == self ? none : merge(criteria)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|