filterable-by 0.6.2 → 0.6.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a92cb2cde41910a93ed81348238f61031c3e5c8071ab2b118bfceb25307a8c14
4
- data.tar.gz: 231b7712b1fe257b34ab63d8a3dc362304c45318984c3eb1a2c8cf004ef2ee44
3
+ metadata.gz: d541006f941920a96920cf443f67353e4c410e1c4d8acb2364902a271e2dfec3
4
+ data.tar.gz: 3a9e964d67aaca1a133c61c3aee729c8c71a2e918f00dcecac9f86eec2c68430
5
5
  SHA512:
6
- metadata.gz: 8ca4f69341eaa58f296280b703398c5ce6ad1dcd6551758322c36a03db7f2b9af7e37defeb96c205a5a1520f40e154d4ebd2f5c6110591ccb1505f55f99ac870
7
- data.tar.gz: 10691ed7dc8e33b7c6920e8a8e6e670b854bc51d6155baa0923d0cfe363ec2fb8824ed79f3cc635cc9b68f824e3c1951ea32cda8e320e0f40b5ad12fbfa37c2f
6
+ metadata.gz: 99d8c2a9440c69950cf5175f713180fffd5f8e801e9ce52568cf3ae908fe18fb0c0f2dfa11a9e4a095351b9a5e70df8c54ed305ec175400f550a3f4d9277d82a
7
+ data.tar.gz: 06ba1b5090fb7425259764e550c8b5d26c82f0f67c8e54205ac3281f1e47ad070c8a89a398e55cd9406eba6c83a47d892b2480d8a47c66d77b345657a067607e
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby-version: ["2.7", "3.0", "3.1"]
14
+ ruby-version: ["2.7", "3.0", "3.1", "3.2"]
15
15
  gemfiles: ["Gemfile", "Gemfile.rails6"]
16
16
  env:
17
17
  BUNDLE_GEMFILE: ${{ matrix.gemfile }}
data/Gemfile CHANGED
@@ -1,2 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
+
4
+ gem 'rake'
5
+ gem 'rspec'
6
+ gem 'rubocop-bsm'
7
+ gem 'sqlite3'
data/Gemfile.lock CHANGED
@@ -1,77 +1,84 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- filterable-by (0.6.2)
4
+ filterable-by (0.6.4)
5
5
  activerecord
6
6
  activesupport
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (7.0.2.3)
12
- activesupport (= 7.0.2.3)
13
- activerecord (7.0.2.3)
14
- activemodel (= 7.0.2.3)
15
- activesupport (= 7.0.2.3)
16
- activesupport (7.0.2.3)
11
+ activemodel (7.0.4.2)
12
+ activesupport (= 7.0.4.2)
13
+ activerecord (7.0.4.2)
14
+ activemodel (= 7.0.4.2)
15
+ activesupport (= 7.0.4.2)
16
+ activesupport (7.0.4.2)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
20
20
  tzinfo (~> 2.0)
21
21
  ast (2.4.2)
22
- concurrent-ruby (1.1.10)
22
+ concurrent-ruby (1.2.0)
23
23
  diff-lcs (1.5.0)
24
- i18n (1.10.0)
24
+ i18n (1.12.0)
25
25
  concurrent-ruby (~> 1.0)
26
- minitest (5.15.0)
26
+ json (2.6.3)
27
+ mini_portile2 (2.8.1)
28
+ minitest (5.17.0)
27
29
  parallel (1.22.1)
28
- parser (3.1.1.0)
30
+ parser (3.2.0.0)
29
31
  ast (~> 2.4.1)
30
32
  rainbow (3.1.1)
31
33
  rake (13.0.6)
32
- regexp_parser (2.2.1)
34
+ regexp_parser (2.6.2)
33
35
  rexml (3.2.5)
34
- rspec (3.11.0)
35
- rspec-core (~> 3.11.0)
36
- rspec-expectations (~> 3.11.0)
37
- rspec-mocks (~> 3.11.0)
38
- rspec-core (3.11.0)
39
- rspec-support (~> 3.11.0)
40
- rspec-expectations (3.11.0)
36
+ rspec (3.12.0)
37
+ rspec-core (~> 3.12.0)
38
+ rspec-expectations (~> 3.12.0)
39
+ rspec-mocks (~> 3.12.0)
40
+ rspec-core (3.12.0)
41
+ rspec-support (~> 3.12.0)
42
+ rspec-expectations (3.12.2)
41
43
  diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.11.0)
43
- rspec-mocks (3.11.1)
44
+ rspec-support (~> 3.12.0)
45
+ rspec-mocks (3.12.3)
44
46
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.11.0)
46
- rspec-support (3.11.0)
47
- rubocop (1.26.1)
47
+ rspec-support (~> 3.12.0)
48
+ rspec-support (3.12.0)
49
+ rubocop (1.44.1)
50
+ json (~> 2.3)
48
51
  parallel (~> 1.10)
49
- parser (>= 3.1.0.0)
52
+ parser (>= 3.2.0.0)
50
53
  rainbow (>= 2.2.2, < 4.0)
51
54
  regexp_parser (>= 1.8, < 3.0)
52
- rexml
53
- rubocop-ast (>= 1.16.0, < 2.0)
55
+ rexml (>= 3.2.5, < 4.0)
56
+ rubocop-ast (>= 1.24.1, < 2.0)
54
57
  ruby-progressbar (~> 1.7)
55
- unicode-display_width (>= 1.4.0, < 3.0)
56
- rubocop-ast (1.16.0)
58
+ unicode-display_width (>= 2.4.0, < 3.0)
59
+ rubocop-ast (1.24.1)
57
60
  parser (>= 3.1.1.0)
58
- rubocop-bsm (0.6.0)
61
+ rubocop-bsm (0.6.1)
59
62
  rubocop (~> 1.0)
60
63
  rubocop-performance
61
64
  rubocop-rake
62
65
  rubocop-rspec
63
- rubocop-performance (1.13.3)
66
+ rubocop-capybara (2.17.0)
67
+ rubocop (~> 1.41)
68
+ rubocop-performance (1.15.2)
64
69
  rubocop (>= 1.7.0, < 2.0)
65
70
  rubocop-ast (>= 0.4.0)
66
71
  rubocop-rake (0.6.0)
67
72
  rubocop (~> 1.0)
68
- rubocop-rspec (2.9.0)
69
- rubocop (~> 1.19)
73
+ rubocop-rspec (2.18.1)
74
+ rubocop (~> 1.33)
75
+ rubocop-capybara (~> 2.17)
70
76
  ruby-progressbar (1.11.0)
71
- sqlite3 (1.4.2)
72
- tzinfo (2.0.4)
77
+ sqlite3 (1.6.0)
78
+ mini_portile2 (~> 2.8.0)
79
+ tzinfo (2.0.6)
73
80
  concurrent-ruby (~> 1.0)
74
- unicode-display_width (2.1.0)
81
+ unicode-display_width (2.4.2)
75
82
 
76
83
  PLATFORMS
77
84
  ruby
@@ -85,4 +92,4 @@ DEPENDENCIES
85
92
  sqlite3
86
93
 
87
94
  BUNDLED WITH
88
- 2.3.6
95
+ 2.3.9
data/Gemfile.rails6 CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  gem 'activerecord', '~> 6.1'
5
+ gem 'rake'
6
+ gem 'rspec'
7
+ gem 'rubocop-bsm'
8
+ gem 'sqlite3'
data/Gemfile.rails6.lock CHANGED
@@ -1,79 +1,84 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- filterable-by (0.6.1)
4
+ filterable-by (0.6.4)
5
5
  activerecord
6
6
  activesupport
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (6.1.4.7)
12
- activesupport (= 6.1.4.7)
13
- activerecord (6.1.4.7)
14
- activemodel (= 6.1.4.7)
15
- activesupport (= 6.1.4.7)
16
- activesupport (6.1.4.7)
11
+ activemodel (6.1.7.2)
12
+ activesupport (= 6.1.7.2)
13
+ activerecord (6.1.7.2)
14
+ activemodel (= 6.1.7.2)
15
+ activesupport (= 6.1.7.2)
16
+ activesupport (6.1.7.2)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
20
20
  tzinfo (~> 2.0)
21
21
  zeitwerk (~> 2.3)
22
22
  ast (2.4.2)
23
- concurrent-ruby (1.1.9)
23
+ concurrent-ruby (1.2.0)
24
24
  diff-lcs (1.5.0)
25
- i18n (1.10.0)
25
+ i18n (1.12.0)
26
26
  concurrent-ruby (~> 1.0)
27
- minitest (5.15.0)
28
- parallel (1.21.0)
29
- parser (3.1.1.0)
27
+ json (2.6.3)
28
+ minitest (5.17.0)
29
+ parallel (1.22.1)
30
+ parser (3.2.0.0)
30
31
  ast (~> 2.4.1)
31
32
  rainbow (3.1.1)
32
33
  rake (13.0.6)
33
- regexp_parser (2.2.1)
34
+ regexp_parser (2.6.2)
34
35
  rexml (3.2.5)
35
- rspec (3.11.0)
36
- rspec-core (~> 3.11.0)
37
- rspec-expectations (~> 3.11.0)
38
- rspec-mocks (~> 3.11.0)
39
- rspec-core (3.11.0)
40
- rspec-support (~> 3.11.0)
41
- rspec-expectations (3.11.0)
36
+ rspec (3.12.0)
37
+ rspec-core (~> 3.12.0)
38
+ rspec-expectations (~> 3.12.0)
39
+ rspec-mocks (~> 3.12.0)
40
+ rspec-core (3.12.0)
41
+ rspec-support (~> 3.12.0)
42
+ rspec-expectations (3.12.2)
42
43
  diff-lcs (>= 1.2.0, < 2.0)
43
- rspec-support (~> 3.11.0)
44
- rspec-mocks (3.11.0)
44
+ rspec-support (~> 3.12.0)
45
+ rspec-mocks (3.12.3)
45
46
  diff-lcs (>= 1.2.0, < 2.0)
46
- rspec-support (~> 3.11.0)
47
- rspec-support (3.11.0)
48
- rubocop (1.26.0)
47
+ rspec-support (~> 3.12.0)
48
+ rspec-support (3.12.0)
49
+ rubocop (1.44.1)
50
+ json (~> 2.3)
49
51
  parallel (~> 1.10)
50
- parser (>= 3.1.0.0)
52
+ parser (>= 3.2.0.0)
51
53
  rainbow (>= 2.2.2, < 4.0)
52
54
  regexp_parser (>= 1.8, < 3.0)
53
- rexml
54
- rubocop-ast (>= 1.16.0, < 2.0)
55
+ rexml (>= 3.2.5, < 4.0)
56
+ rubocop-ast (>= 1.24.1, < 2.0)
55
57
  ruby-progressbar (~> 1.7)
56
- unicode-display_width (>= 1.4.0, < 3.0)
57
- rubocop-ast (1.16.0)
58
+ unicode-display_width (>= 2.4.0, < 3.0)
59
+ rubocop-ast (1.24.1)
58
60
  parser (>= 3.1.1.0)
59
- rubocop-bsm (0.6.0)
61
+ rubocop-bsm (0.6.1)
60
62
  rubocop (~> 1.0)
61
63
  rubocop-performance
62
64
  rubocop-rake
63
65
  rubocop-rspec
64
- rubocop-performance (1.13.3)
66
+ rubocop-capybara (2.17.0)
67
+ rubocop (~> 1.41)
68
+ rubocop-performance (1.15.2)
65
69
  rubocop (>= 1.7.0, < 2.0)
66
70
  rubocop-ast (>= 0.4.0)
67
71
  rubocop-rake (0.6.0)
68
72
  rubocop (~> 1.0)
69
- rubocop-rspec (2.9.0)
70
- rubocop (~> 1.19)
73
+ rubocop-rspec (2.18.1)
74
+ rubocop (~> 1.33)
75
+ rubocop-capybara (~> 2.17)
71
76
  ruby-progressbar (1.11.0)
72
- sqlite3 (1.4.2)
73
- tzinfo (2.0.4)
77
+ sqlite3 (1.6.0-x86_64-linux)
78
+ tzinfo (2.0.6)
74
79
  concurrent-ruby (~> 1.0)
75
- unicode-display_width (2.1.0)
76
- zeitwerk (2.5.4)
80
+ unicode-display_width (2.4.2)
81
+ zeitwerk (2.6.6)
77
82
 
78
83
  PLATFORMS
79
84
  x86_64-linux
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'filterable-by'
3
- s.version = '0.6.2'
3
+ s.version = '0.6.4'
4
4
  s.authors = ['Dimitrij Denissenko']
5
5
  s.email = ['dimitrij@blacksquaremedia.com']
6
6
  s.summary = 'Generate white-listed filter scopes from URL parameter values'
@@ -9,7 +9,6 @@ Gem::Specification.new do |s|
9
9
  s.license = 'MIT'
10
10
 
11
11
  s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^spec/}) }
12
- s.test_files = `git ls-files -z -- spec/*`.split("\x0")
13
12
  s.require_paths = ['lib']
14
13
  s.required_ruby_version = '>= 2.7'
15
14
 
@@ -17,9 +16,5 @@ Gem::Specification.new do |s|
17
16
  s.add_dependency 'activesupport'
18
17
 
19
18
  s.add_development_dependency 'bundler'
20
- s.add_development_dependency 'rake'
21
- s.add_development_dependency 'rspec'
22
- s.add_development_dependency 'rubocop-bsm'
23
- s.add_development_dependency 'sqlite3'
24
19
  s.metadata['rubygems_mfa_required'] = 'true'
25
20
  end
data/lib/filterable_by.rb CHANGED
@@ -4,40 +4,56 @@ require 'set'
4
4
 
5
5
  module ActiveRecord
6
6
  module FilterableBy
7
- def self.normalize(value)
8
- case value
9
- when String, Numeric
10
- value
11
- when Array
12
- value.select {|v| normalize(v) }
7
+ class << self
8
+ def normalize(value)
9
+ case value
10
+ when String, Numeric
11
+ value
12
+ when Array
13
+ value.select {|v| normalize(v) }
14
+ end
13
15
  end
14
- end
15
16
 
16
- def self.merge(scope, unscoped, hash, name, **opts, &block)
17
- key = name
18
- positive = normalize(hash[key]) if hash.key?(key)
19
- if positive.present?
20
- sub = block.arity == 2 ? yield(unscoped, positive, **opts) : yield(positive, **opts)
21
- return nil unless sub
17
+ def merge(scope, unscoped, hash, name, **opts, &block)
18
+ key = name
19
+ positive = normalize(hash[key]) if hash.key?(key)
20
+ if positive.present?
21
+ sub = eval_scope(scope, unscoped, positive, **opts, &block)
22
+ return nil unless sub
23
+
24
+ scope = scope.merge(sub)
25
+ end
26
+
27
+ key = "#{name}_not"
28
+ negative = normalize(hash[key]) if hash.key?(key)
29
+ if negative.present?
30
+ sub = eval_scope(scope, unscoped, negative, **opts, &block)
31
+ return nil unless sub
22
32
 
23
- scope = scope.merge(sub)
33
+ scope = scope.merge(invert_where(sub))
34
+ end
35
+
36
+ scope
24
37
  end
25
38
 
26
- key = "#{name}_not"
27
- negative = normalize(hash[key]) if hash.key?(key)
28
- if negative.present?
29
- sub = block.arity == 2 ? yield(unscoped, negative, **opts) : yield(negative, **opts)
30
- return nil unless sub
39
+ private
31
40
 
32
- if sub.respond_to?(:invert_where)
33
- sub = sub.invert_where
41
+ def eval_scope(scope, unscoped, value, **opts, &block)
42
+ if block.arity == 2
43
+ scope.instance_exec(unscoped, value, **opts, &block)
34
44
  else
35
- sub.where_clause = sub.where_clause.invert
45
+ scope.instance_exec(value, **opts, &block)
36
46
  end
37
- scope = scope.merge(sub)
38
47
  end
39
48
 
40
- scope
49
+ def invert_where(scope)
50
+ if scope.respond_to?(:invert_where!)
51
+ scope.invert_where!
52
+ else
53
+ scope.where_clause = scope.where_clause.invert
54
+ end
55
+ scope
56
+ end
41
57
  end
42
58
 
43
59
  module ClassMethods
@@ -58,7 +74,7 @@ module ActiveRecord
58
74
  end
59
75
 
60
76
  names.each do |name|
61
- _filterable_by_config[name.to_s] = block
77
+ _filterable_by_config[name.to_s] = block || ->(value, **) { where(name.to_sym => value) }
62
78
  end
63
79
  end
64
80
 
@@ -74,7 +90,6 @@ module ActiveRecord
74
90
  return scope unless hash.respond_to?(:key?) && hash.respond_to?(:[])
75
91
 
76
92
  _filterable_by_config.each do |name, block|
77
- block = ->(value, **) { where(name.to_sym => value) } if block.nil?
78
93
  scope = FilterableBy.merge(scope, unscoped, hash, name, **opts, &block)
79
94
  break unless scope
80
95
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filterable-by
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-05 00:00:00.000000000 Z
11
+ date: 2023-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -52,62 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-bsm
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: sqlite3
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
55
  description: ActiveRecord plugin
112
56
  email:
113
57
  - dimitrij@blacksquaremedia.com
@@ -128,8 +72,6 @@ files:
128
72
  - filterable-by.gemspec
129
73
  - lib/filterable-by.rb
130
74
  - lib/filterable_by.rb
131
- - spec/active_record/filterable_by_spec.rb
132
- - spec/spec_helper.rb
133
75
  homepage: https://github.com/bsm/filterable-by
134
76
  licenses:
135
77
  - MIT
@@ -154,6 +96,4 @@ rubygems_version: 3.3.3
154
96
  signing_key:
155
97
  specification_version: 4
156
98
  summary: Generate white-listed filter scopes from URL parameter values
157
- test_files:
158
- - spec/active_record/filterable_by_spec.rb
159
- - spec/spec_helper.rb
99
+ test_files: []
@@ -1,104 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveRecord::FilterableBy do
4
- let(:alice) { AUTHORS[:alice] }
5
- let(:bob) { AUTHORS[:bob] }
6
-
7
- let(:apost) { POSTS[:alices] }
8
- let(:bpost) { POSTS[:bobs] }
9
-
10
- it 'has config' do
11
- expect(Comment.send(:_filterable_by_config).count).to eq(5)
12
- expect(Rating.send(:_filterable_by_config).count).to eq(4)
13
- expect(Post.send(:_filterable_by_config).count).to eq(2)
14
- end
15
-
16
- it 'ignores bad inputs' do
17
- expect(Comment.filter_by.count).to eq(4)
18
- expect(Comment.filter_by(nil).count).to eq(4)
19
- expect(Comment.filter_by(nil, extra: true).count).to eq(4)
20
- expect(Comment.filter_by('bad').count).to eq(4)
21
-
22
- expect(Comment.filter_by('author_id' => '').count).to eq(4)
23
- expect(Comment.filter_by('author_id' => []).count).to eq(4)
24
- end
25
-
26
- it 'generates simple scopes' do
27
- expect(Comment.filter_by('author_id' => alice.id).pluck(:title)).to match_array(%w[AA AB])
28
- expect(Comment.filter_by('author_id' => bob.id).pluck(:title)).to match_array(%w[BA BB])
29
- expect(Comment.filter_by('author_id' => [alice.id, '']).pluck(:title)).to match_array(%w[AA AB])
30
-
31
- expect(Comment.filter_by('post_id' => apost.id).pluck(:title)).to match_array(%w[AA BA])
32
- expect(Comment.filter_by('post_id' => bpost.id).pluck(:title)).to match_array(%w[AB BB])
33
-
34
- expect(Comment.filter_by('post_author_id' => alice.id).pluck(:title)).to match_array(%w[AA BA])
35
- expect(Comment.filter_by('post_author_id' => bob.id).pluck(:title)).to match_array(%w[AB BB])
36
-
37
- expect(Rating.filter_by('author_id' => alice.id).count).to eq(0)
38
- expect(Rating.filter_by('author_id' => bob.id).count).to eq(1)
39
-
40
- expect(Post.filter_by('author_id' => bob.id).count).to eq(1)
41
- end
42
-
43
- it 'generates combined scopes' do
44
- expect(Comment.filter_by('author_id' => alice.id, 'post_id' => apost.id).pluck(:title)).to match_array(['AA'])
45
- expect(Comment.filter_by('author_id' => alice.id, 'post_id' => bpost.id).pluck(:title)).to match_array(['AB'])
46
- expect(Comment.filter_by('author_id' => bob.id, 'post_id' => apost.id).pluck(:title)).to match_array(['BA'])
47
- expect(Comment.filter_by('author_id' => bob.id, 'post_id' => bpost.id).pluck(:title)).to match_array(['BB'])
48
-
49
- scope = Comment.filter_by('author_id' => [alice.id, bob.id], 'post_id' => bpost.id)
50
- expect(scope.pluck(:title)).to match_array(%w[AB BB])
51
- end
52
-
53
- it 'generates negated scopes' do
54
- expect(Comment.filter_by('author_id_not' => alice.id).pluck(:title)).to match_array(%w[BA BB])
55
- expect(Comment.filter_by('author_id_not' => [alice.id, bob.id]).pluck(:title)).to match_array(%w[])
56
- expect(Comment.filter_by('post_id_not' => apost.id).pluck(:title)).to match_array(%w[AB BB])
57
- expect(Comment.filter_by('post_author_id_not' => alice.id).pluck(:title)).to match_array(%w[AB BB])
58
- expect(Comment.filter_by('author_id' => bob.id, 'post_id_not' => bpost.id).pluck(:title)).to match_array(['BA'])
59
- end
60
-
61
- it 'combines with other scopes' do
62
- scope = Comment.where(author_id: alice.id).filter_by('post_id' => apost.id)
63
- expect(scope.pluck(:title)).to match_array(['AA'])
64
-
65
- expect(alice.posts.filter_by('post_id' => apost.id).count).to be(1)
66
- expect(alice.posts.filter_by('author_id' => alice.id).count).to be(1)
67
- expect(alice.posts.filter_by('author_id_not' => bob.id).count).to be(1)
68
- expect(alice.posts.filter_by('author_id' => bob.id).count).to be_zero
69
- expect(alice.posts.filter_by('author_id_not' => alice.id).count).to be_zero
70
- end
71
-
72
- it 'allows custom options' do
73
- scope = Post.filter_by({ 'only' => 'me' }, user_id: alice.id)
74
- expect(scope).to match_array([apost])
75
-
76
- scope = Post.filter_by({ 'only' => '??' }, user_id: alice.id)
77
- expect(scope.count).to eq(2)
78
-
79
- scope = Post.filter_by({ 'only' => 'me' })
80
- expect(scope.count).to eq(0)
81
- end
82
-
83
- it 'allows custom options from params' do
84
- filter = { 'only' => 'me' }
85
- expect(Post.filter_by(filter, user_id: alice.id)).to match_array([apost])
86
- expect(Post.filter_by(filter).count).to eq(0)
87
- end
88
-
89
- it 'ignores invalid scopes' do
90
- expect(Comment.filter_by('invalid' => 1).count).to eq(4)
91
- expect(Post.filter_by('post_id' => bpost.id).count).to eq(2)
92
- expect(Rating.filter_by('post_author_id' => bob.id).count).to eq(1)
93
- end
94
-
95
- it 'supports deprecated scoping' do
96
- expect(Comment.filter_by('deprecated' => alice.id).pluck(:title)).to match_array(%w[AA AB])
97
- expect(Comment.filter_by('deprecated_with_opts' => alice.id).pluck(:title)).to match_array(%w[AA AB])
98
- expect(Comment.filter_by('deprecated_not' => alice.id).pluck(:title)).to match_array(%w[BA BB])
99
- end
100
-
101
- it 'supports abstract classes' do
102
- expect(Post.filter_by('author_id' => bob.id).count).to eq(1)
103
- end
104
- end
data/spec/spec_helper.rb DELETED
@@ -1,87 +0,0 @@
1
- ENV['RACK_ENV'] ||= 'test'
2
- require 'filterable-by'
3
- require 'rspec'
4
-
5
- ActiveRecord::Base.configurations = { 'test' => { 'adapter' => 'sqlite3', 'database' => ':memory:' } }
6
- ActiveRecord::Base.establish_connection :test
7
-
8
- ActiveRecord::Base.connection.instance_eval do
9
- create_table :authors do |_|
10
- # no columns
11
- end
12
- create_table :posts do |t|
13
- t.integer :author_id, null: false
14
- end
15
- create_table :feedbacks do |t|
16
- t.string :type, null: false
17
- t.string :title
18
- t.integer :stars, null: false, default: 0
19
- t.integer :post_id, null: false
20
- t.integer :author_id, null: false
21
- end
22
- end
23
-
24
- class Author < ActiveRecord::Base
25
- has_many :posts
26
- end
27
-
28
- class AbstractPost < ActiveRecord::Base
29
- self.abstract_class = true
30
- filterable_by :author_id
31
- end
32
-
33
- class Post < AbstractPost
34
- belongs_to :author
35
-
36
- filterable_by :only do |value, **opts|
37
- case value
38
- when 'me'
39
- where(author_id: opts[:user_id]) if opts[:user_id]
40
- else
41
- all
42
- end
43
- end
44
- end
45
-
46
- class Feedback < ActiveRecord::Base
47
- belongs_to :author
48
- belongs_to :post
49
-
50
- filterable_by :post_id, :author_id
51
-
52
- ActiveSupport::Deprecation.silence do
53
- filterable_by :deprecated do |scope, value|
54
- scope.where(author_id: value)
55
- end
56
- filterable_by :deprecated_with_opts do |scope, value, **_opts|
57
- scope.where(author_id: value)
58
- end
59
- end
60
- end
61
-
62
- class Comment < Feedback
63
- filterable_by :post_author_id do |value|
64
- joins(:post).where(Post.arel_table[:author_id].eq(value))
65
- end
66
- end
67
-
68
- class Rating < Feedback
69
- end
70
-
71
- AUTHORS = {
72
- alice: Author.create!,
73
- bob: Author.create!,
74
- }.freeze
75
-
76
- POSTS = {
77
- alices: Post.create!(author_id: AUTHORS[:alice].id),
78
- bobs: Post.create!(author_id: AUTHORS[:bob].id),
79
- }.freeze
80
-
81
- COMMENTS = {
82
- alice_on_alice: Comment.create!(title: 'AA', post_id: POSTS[:alices].id, author_id: AUTHORS[:alice].id),
83
- bob_on_alice: Comment.create!(title: 'BA', post_id: POSTS[:alices].id, author_id: AUTHORS[:bob].id),
84
- alice_on_bob: Comment.create!(title: 'AB', post_id: POSTS[:bobs].id, author_id: AUTHORS[:alice].id),
85
- bob_on_bob: Comment.create!(title: 'BB', post_id: POSTS[:bobs].id, author_id: AUTHORS[:bob].id),
86
- boa_rating: Rating.create!(stars: 5, post_id: POSTS[:alices].id, author_id: AUTHORS[:bob].id),
87
- }.freeze