filterable-by 0.5.0 → 0.5.1

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: 1369751aa86d400aa27ab43ad4cdbbcc92ff06a2ca19162582f8c95914882814
4
- data.tar.gz: ca8d93901d61b20377196045430f22e63bf622e05abdab58ec4f85a578526458
3
+ metadata.gz: ae571004dd8c2aebddad1f69b8a698b7f52f0fa5bb2d3338a74de5f6a9e18e1a
4
+ data.tar.gz: f1744d312f8b99eab4ada84590b65361e1cb183ef3a41ce1969569ca723880e5
5
5
  SHA512:
6
- metadata.gz: 5e487f8f1e5337faaaf0a25c009ded133b78f21a89c07b49b4d81ead360b6cbfb1a21acb4787ff96b2e5d35931ed126f42c1d1acdfa6b23b8d8ad190da260a41
7
- data.tar.gz: e68b17a74b428364b6bb46bf92da38f18b0fda824eef32823af567b336f172ef011c2dd15a904e41accad29ea0e0c103f078e8949a30dedd08c7a6b96407152b
6
+ metadata.gz: ce8c6eabe14c36dd917c8f30f29926a6ae88baa494067683912f63dd3af6445ca93b74426e1d24c3f8992e2d740d340a4bbb8b494c033872fb1a0ed51924e085
7
+ data.tar.gz: eed08234ac28e40f99fc786225bc2e65ead127808e93714d8747a30fcb0c4a01fe27b450f4dfa9de713d08d05cd1c65c2e6c4412402a0567b48d5f05a1b1011b
@@ -1,5 +1,6 @@
1
1
  rvm:
2
2
  - 2.5
3
3
  - 2.6
4
+ - 2.7
4
5
  gemfile:
5
6
  - Gemfile
@@ -1,63 +1,68 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- filterable-by (0.5.0)
4
+ filterable-by (0.5.1)
5
5
  activerecord
6
6
  activesupport
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (6.0.0)
12
- activesupport (= 6.0.0)
13
- activerecord (6.0.0)
14
- activemodel (= 6.0.0)
15
- activesupport (= 6.0.0)
16
- activesupport (6.0.0)
11
+ activemodel (6.0.3.2)
12
+ activesupport (= 6.0.3.2)
13
+ activerecord (6.0.3.2)
14
+ activemodel (= 6.0.3.2)
15
+ activesupport (= 6.0.3.2)
16
+ activesupport (6.0.3.2)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 0.7, < 2)
19
19
  minitest (~> 5.1)
20
20
  tzinfo (~> 1.1)
21
- zeitwerk (~> 2.1, >= 2.1.8)
22
- ast (2.4.0)
23
- concurrent-ruby (1.1.5)
24
- diff-lcs (1.3)
25
- i18n (1.6.0)
21
+ zeitwerk (~> 2.2, >= 2.2.2)
22
+ ast (2.4.1)
23
+ concurrent-ruby (1.1.6)
24
+ diff-lcs (1.4.4)
25
+ i18n (1.8.3)
26
26
  concurrent-ruby (~> 1.0)
27
- jaro_winkler (1.5.3)
28
- minitest (5.11.3)
29
- parallel (1.17.0)
30
- parser (2.6.3.0)
31
- ast (~> 2.4.0)
27
+ minitest (5.14.1)
28
+ parallel (1.19.2)
29
+ parser (2.7.1.4)
30
+ ast (~> 2.4.1)
32
31
  rainbow (3.0.0)
33
- rake (12.3.3)
34
- rspec (3.8.0)
35
- rspec-core (~> 3.8.0)
36
- rspec-expectations (~> 3.8.0)
37
- rspec-mocks (~> 3.8.0)
38
- rspec-core (3.8.2)
39
- rspec-support (~> 3.8.0)
40
- rspec-expectations (3.8.4)
32
+ rake (13.0.1)
33
+ regexp_parser (1.7.1)
34
+ rexml (3.2.4)
35
+ rspec (3.9.0)
36
+ rspec-core (~> 3.9.0)
37
+ rspec-expectations (~> 3.9.0)
38
+ rspec-mocks (~> 3.9.0)
39
+ rspec-core (3.9.2)
40
+ rspec-support (~> 3.9.3)
41
+ rspec-expectations (3.9.2)
41
42
  diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.8.0)
43
- rspec-mocks (3.8.1)
43
+ rspec-support (~> 3.9.0)
44
+ rspec-mocks (3.9.1)
44
45
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.8.0)
46
- rspec-support (3.8.2)
47
- rubocop (0.74.0)
48
- jaro_winkler (~> 1.5.1)
46
+ rspec-support (~> 3.9.0)
47
+ rspec-support (3.9.3)
48
+ rubocop (0.87.1)
49
49
  parallel (~> 1.10)
50
- parser (>= 2.6)
50
+ parser (>= 2.7.1.1)
51
51
  rainbow (>= 2.2.2, < 4.0)
52
+ regexp_parser (>= 1.7)
53
+ rexml
54
+ rubocop-ast (>= 0.1.0, < 1.0)
52
55
  ruby-progressbar (~> 1.7)
53
- unicode-display_width (>= 1.4.0, < 1.7)
56
+ unicode-display_width (>= 1.4.0, < 2.0)
57
+ rubocop-ast (0.1.0)
58
+ parser (>= 2.7.0.1)
54
59
  ruby-progressbar (1.10.1)
55
- sqlite3 (1.4.1)
60
+ sqlite3 (1.4.2)
56
61
  thread_safe (0.3.6)
57
- tzinfo (1.2.5)
62
+ tzinfo (1.2.7)
58
63
  thread_safe (~> 0.1)
59
- unicode-display_width (1.6.0)
60
- zeitwerk (2.1.9)
64
+ unicode-display_width (1.7.0)
65
+ zeitwerk (2.3.1)
61
66
 
62
67
  PLATFORMS
63
68
  ruby
@@ -71,4 +76,4 @@ DEPENDENCIES
71
76
  sqlite3
72
77
 
73
78
  BUNDLED WITH
74
- 2.0.2
79
+ 2.1.4
data/README.md CHANGED
@@ -16,22 +16,33 @@ class Comment < ActiveRecord::Base
16
16
 
17
17
  filterable_by :post_id, :user_id
18
18
  filterable_by :post_author_id do |scope, value|
19
- scope.joins(:posts).where(:"posts.author_id" => value)
19
+ scope.joins(:posts).where(:'posts.author_id' => value)
20
+ end
21
+ filterable_by :only do |scope, value, **opts|
22
+ case value
23
+ when 'mine'
24
+ scope.where(user_id: opts[:user_id]) if opts[:user_id]
25
+ else
26
+ scope
27
+ end
20
28
  end
21
29
  end
22
30
 
23
- Comment.filter_by(params[:filter]) # => ActiveRecord::Relation
31
+ Comment.filter_by(params[:filter], user_id: current_user.id) # => ActiveRecord::Relation
24
32
  ```
25
33
 
26
34
  Simple use cases:
27
35
 
28
36
  ```ruby
29
- Comment.filter_by({ "post_id" => "1" })
37
+ Comment.filter_by({ 'post_id' => '1' })
30
38
  # => WHERE post_id = 1
31
39
 
32
- Comment.filter_by({ "user_id" => "2", "ignored" => "3" })
40
+ Comment.filter_by({ 'user_id' => '2', 'ignored' => '3' })
33
41
  # => WHERE user_id = 2
34
42
 
35
- Comment.filter_by({ "post_author_id" => "5" })
43
+ Comment.filter_by({ 'only' => 'mine' }, user_id: 4)
44
+ # => WHERE user_id = 4
45
+
46
+ Comment.filter_by({ 'post_author_id' => '5' })
36
47
  # => JOINS posts ON posts.id = comments.post_id WHERE posts.author_id = 5
37
48
  ```
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'filterable-by'
3
- s.version = '0.5.0'
3
+ s.version = '0.5.1'
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'
@@ -27,13 +27,17 @@ module ActiveRecord
27
27
 
28
28
  def filterable_by(*names, &block)
29
29
  names.each do |name|
30
- _filterable_by_config[name.to_s] = block || ->(scope, v) { scope.where(name.to_sym => v) }
30
+ _filterable_by_config[name.to_s] = block || ->(scope, value, **) { scope.where(name.to_sym => value) }
31
31
  end
32
32
  end
33
33
 
34
34
  # @param [Hash] hash the filter params
35
35
  # @return [ActiveRecord::Relation] the scoped relation
36
- def filter_by(hash)
36
+ def filter_by(hash = nil, **opts)
37
+ if hash.nil?
38
+ hash = opts
39
+ opts = {}
40
+ end
37
41
  scope = all
38
42
  return scope unless hash.is_a?(Hash)
39
43
 
@@ -43,9 +47,10 @@ module ActiveRecord
43
47
  value = FilterableBy.normalize(hash[name])
44
48
  next if value.blank?
45
49
 
46
- scope = block.call(scope, value)
50
+ scope = block.call(scope, value, **opts)
47
51
  end
48
- scope
52
+
53
+ scope || none
49
54
  end
50
55
  end
51
56
  end
@@ -10,12 +10,14 @@ describe ActiveRecord::FilterableBy do
10
10
  it 'should have config' do
11
11
  expect(Comment.send(:_filterable_by_config).count).to eq(3)
12
12
  expect(Rating.send(:_filterable_by_config).count).to eq(2)
13
- expect(Post.send(:_filterable_by_config).count).to eq(1)
13
+ expect(Post.send(:_filterable_by_config).count).to eq(2)
14
14
  end
15
15
 
16
16
  it 'should ignore bad inputs' do
17
+ expect(Comment.filter_by.count).to eq(4)
17
18
  expect(Comment.filter_by(nil).count).to eq(4)
18
- expect(Comment.filter_by({}).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)
19
21
 
20
22
  expect(Comment.filter_by('author_id' => '').count).to eq(4)
21
23
  expect(Comment.filter_by('author_id' => []).count).to eq(4)
@@ -53,6 +55,23 @@ describe ActiveRecord::FilterableBy do
53
55
  expect(scope.pluck(:title)).to match_array(['AA'])
54
56
  end
55
57
 
58
+ it 'should allow custom options' do
59
+ scope = Post.filter_by({ 'only' => 'me' }, user_id: alice.id)
60
+ expect(scope).to match_array([apost])
61
+
62
+ scope = Post.filter_by({ 'only' => '??' }, user_id: alice.id)
63
+ expect(scope.count).to eq(2)
64
+
65
+ scope = Post.filter_by({ 'only' => 'me' })
66
+ expect(scope.count).to eq(0)
67
+ end
68
+
69
+ it 'should allow custom options from params' do
70
+ filter = { 'only' => 'me' }
71
+ expect(Post.filter_by(filter, user_id: alice.id)).to match_array([apost])
72
+ expect(Post.filter_by(filter).count).to eq(0)
73
+ end
74
+
56
75
  it 'should ignore invalid scopes' do
57
76
  expect(Comment.filter_by('invalid' => 1).count).to eq(4)
58
77
  expect(Post.filter_by('post_id' => bpost.id).count).to eq(2)
@@ -2,7 +2,7 @@ ENV['RACK_ENV'] ||= 'test'
2
2
  require 'filterable-by'
3
3
  require 'rspec'
4
4
 
5
- ActiveRecord::Base.configurations['test'] = { 'adapter' => 'sqlite3', 'database' => ':memory:' }
5
+ ActiveRecord::Base.configurations = { 'test' => { 'adapter' => 'sqlite3', 'database' => ':memory:' } }
6
6
  ActiveRecord::Base.establish_connection :test
7
7
 
8
8
  ActiveRecord::Base.connection.instance_eval do
@@ -27,6 +27,14 @@ class Post < ActiveRecord::Base
27
27
  belongs_to :author
28
28
 
29
29
  filterable_by :author_id
30
+ filterable_by :only do |scope, value, **opts|
31
+ case value
32
+ when 'me'
33
+ scope.where(author_id: opts[:user_id]) if opts[:user_id]
34
+ else
35
+ scope
36
+ end
37
+ end
30
38
  end
31
39
 
32
40
  class Feedback < ActiveRecord::Base
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.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-27 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  - !ruby/object:Gem::Version
148
148
  version: '0'
149
149
  requirements: []
150
- rubygems_version: 3.0.3
150
+ rubygems_version: 3.1.4
151
151
  signing_key:
152
152
  specification_version: 4
153
153
  summary: Generate white-listed filter scopes from URL parameter values