sortable-by 0.12.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e89dd7025ad14bfd9a012b10d68a70183692121625d14e56feea7e3484d8398
4
- data.tar.gz: 931017877555f573485ebbaecb5501ba36e5e4c3a2c7d0842ada6ff2f68cd5fb
3
+ metadata.gz: 4639f942b5f628b07367a343160d7e4301b00bf3c6e0db9f57ff43d204a85ab5
4
+ data.tar.gz: 2f424ec2cda37112ca64fdf628b7ff0aee3e223dbee81d585040eff79ee468c8
5
5
  SHA512:
6
- metadata.gz: 45ef18f0d53caa91e2e9cb0c8bcbae4bf4cdc3da59b844e1ddae2f5fa16454905d925a7212a31e4355f077fe7436b25303f17422c47f25592a3036cd623caba3
7
- data.tar.gz: 724fd46c5ea0fd379980dcfe64a58ea579d9d03edab02516862d654ccc5a472d10bc810ccf48a32d4cc96e70ed5608100596425091c7a541dae5f380f8f4a173
6
+ metadata.gz: ff08a62e083e324f9baa4118423c82d90ad93d00f42b4cd6ae74d915a637439315f4cf5ebd8b9d598075bd9565064429a06d0017bae3b5f7998c35b39a50f14c
7
+ data.tar.gz: b084242394054b896d594c923e262c6325a74c58c836e2224ee5c4f91c3bc087bedfe0b42eb7aa2438ea2a84dd41ddd54c6b5718f68e181d5869bbb5efcb2397
@@ -4,6 +4,8 @@ inherit_from:
4
4
  AllCops:
5
5
  TargetRubyVersion: 2.5
6
6
 
7
+ Naming/MethodParameterName:
8
+ MinNameLength: 2
7
9
  Naming/MemoizedInstanceVariableName:
8
10
  Enabled: false
9
11
  Naming/FileName:
@@ -2,6 +2,7 @@ sudo: false
2
2
  rvm:
3
3
  - 2.5
4
4
  - 2.6
5
+ - 2.7
5
6
  gemfile:
6
7
  - Gemfile
7
8
  before_install:
@@ -1,41 +1,42 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sortable-by (0.12.1)
4
+ sortable-by (0.13.0)
5
5
  activerecord
6
6
  activesupport
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (6.0.3.1)
12
- activesupport (= 6.0.3.1)
13
- activerecord (6.0.3.1)
14
- activemodel (= 6.0.3.1)
15
- activesupport (= 6.0.3.1)
16
- activesupport (6.0.3.1)
11
+ activemodel (6.0.3.3)
12
+ activesupport (= 6.0.3.3)
13
+ activerecord (6.0.3.3)
14
+ activemodel (= 6.0.3.3)
15
+ activesupport (= 6.0.3.3)
16
+ activesupport (6.0.3.3)
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
21
  zeitwerk (~> 2.2, >= 2.2.2)
22
- ast (2.4.0)
23
- concurrent-ruby (1.1.6)
24
- diff-lcs (1.3)
25
- i18n (1.8.2)
22
+ ast (2.4.1)
23
+ concurrent-ruby (1.1.7)
24
+ diff-lcs (1.4.4)
25
+ i18n (1.8.5)
26
26
  concurrent-ruby (~> 1.0)
27
- minitest (5.14.1)
28
- parallel (1.19.1)
29
- parser (2.7.1.3)
30
- ast (~> 2.4.0)
27
+ minitest (5.14.2)
28
+ parallel (1.19.2)
29
+ parser (2.7.2.0)
30
+ ast (~> 2.4.1)
31
31
  rainbow (3.0.0)
32
32
  rake (13.0.1)
33
+ regexp_parser (1.8.1)
33
34
  rexml (3.2.4)
34
35
  rspec (3.9.0)
35
36
  rspec-core (~> 3.9.0)
36
37
  rspec-expectations (~> 3.9.0)
37
38
  rspec-mocks (~> 3.9.0)
38
- rspec-core (3.9.2)
39
+ rspec-core (3.9.3)
39
40
  rspec-support (~> 3.9.3)
40
41
  rspec-expectations (3.9.2)
41
42
  diff-lcs (>= 1.2.0, < 2.0)
@@ -44,23 +45,24 @@ GEM
44
45
  diff-lcs (>= 1.2.0, < 2.0)
45
46
  rspec-support (~> 3.9.0)
46
47
  rspec-support (3.9.3)
47
- rubocop (0.84.0)
48
+ rubocop (0.92.0)
48
49
  parallel (~> 1.10)
49
- parser (>= 2.7.0.1)
50
+ parser (>= 2.7.1.5)
50
51
  rainbow (>= 2.2.2, < 4.0)
52
+ regexp_parser (>= 1.7)
51
53
  rexml
52
- rubocop-ast (>= 0.0.3)
54
+ rubocop-ast (>= 0.5.0)
53
55
  ruby-progressbar (~> 1.7)
54
56
  unicode-display_width (>= 1.4.0, < 2.0)
55
- rubocop-ast (0.0.3)
56
- parser (>= 2.7.0.1)
57
+ rubocop-ast (0.7.1)
58
+ parser (>= 2.7.1.5)
57
59
  ruby-progressbar (1.10.1)
58
60
  sqlite3 (1.4.2)
59
61
  thread_safe (0.3.6)
60
62
  tzinfo (1.2.7)
61
63
  thread_safe (~> 0.1)
62
64
  unicode-display_width (1.7.0)
63
- zeitwerk (2.3.0)
65
+ zeitwerk (2.4.0)
64
66
 
65
67
  PLATFORMS
66
68
  ruby
@@ -74,4 +76,4 @@ DEPENDENCIES
74
76
  sqlite3
75
77
 
76
78
  BUNDLED WITH
77
- 2.1.2
79
+ 2.1.4
data/README.md CHANGED
@@ -20,23 +20,23 @@ class Post < ActiveRecord::Base
20
20
  sortable_by :title, :id
21
21
  end
22
22
 
23
- Post.sorted_by('title') # => ORDER BY posts.title ASC
24
- Post.sorted_by('-title') # => ORDER BY posts.title DESC
25
- Post.sorted_by('bad,title') # => ORDER BY posts.title ASC
26
- Post.sorted_by(nil) # => ORDER BY posts.title ASC
23
+ Post.sorted_by('title') # => ORDER BY LOWER(posts.title) ASC
24
+ Post.sorted_by('-title') # => ORDER BY LOWER(posts.title) DESC
25
+ Post.sorted_by('bad,title') # => ORDER BY LOWER(posts.title) ASC
26
+ Post.sorted_by(nil) # => ORDER BY LOWER(posts.title) ASC
27
27
  ```
28
28
 
29
- Case-insensitive:
29
+ Case-sensitive:
30
30
 
31
31
  ```ruby
32
32
  class Post < ActiveRecord::Base
33
33
  sortable_by do |x|
34
- x.field :title, as: arel_table[:title].lower
34
+ x.field :title, case_sensitive: true
35
35
  x.field :id
36
36
  end
37
37
  end
38
38
 
39
- Post.sorted_by('title') # => ORDER BY LOWER(posts.title) ASC
39
+ Post.sorted_by('title') # => ORDER BY posts.title ASC
40
40
  ```
41
41
 
42
42
  With custom default:
@@ -46,7 +46,7 @@ class Post < ActiveRecord::Base
46
46
  sortable_by :id, :topic, :created_at, default: 'topic,-created_at'
47
47
  end
48
48
 
49
- Post.sorted_by(nil) # => ORDER BY posts.topic ASC, posts.created_at DESC
49
+ Post.sorted_by(nil) # => ORDER BY LOWER(posts.topic) ASC, posts.created_at DESC
50
50
  ```
51
51
 
52
52
  Composition:
@@ -68,8 +68,8 @@ Associations (eager load):
68
68
  class Product < ActiveRecord::Base
69
69
  belongs_to :shop
70
70
  sortable_by do |x|
71
- x.field :name, as: arel_table[:name].lower
72
- x.field :shop, as: Shop.arel_table[:name].lower, eager_load: :shop
71
+ x.field :name
72
+ x.field :shop, as: Shop.arel_table[:name], eager_load: :shop
73
73
  x.default 'shop,name'
74
74
  end
75
75
  end
@@ -77,11 +77,11 @@ end
77
77
 
78
78
  Associations (custom scope):
79
79
 
80
- ```
80
+ ```ruby
81
81
  class Product < ActiveRecord::Base
82
82
  belongs_to :shop
83
83
  sortable_by do |x|
84
- x.field :shop, as: Shop.arel_table[:name].lower, scope: -> { joins(:shop) }
84
+ x.field :shop, as: Shop.arel_table[:name], scope: -> { joins(:shop) }
85
85
  end
86
86
  end
87
87
  ```
@@ -17,9 +17,9 @@ module ActiveRecord # :nodoc:
17
17
  duplicate
18
18
  end
19
19
 
20
- def field(name, opts = {})
20
+ def field(name, **opts)
21
21
  name = name.to_s
22
- @_fields[name] = Field.new(name, opts)
22
+ @_fields[name] = Field.new(name, **opts)
23
23
  @_default ||= name
24
24
  end
25
25
 
@@ -36,7 +36,7 @@ module ActiveRecord # :nodoc:
36
36
 
37
37
  protected
38
38
 
39
- def order(relation, expr, fallback = true)
39
+ def order(relation, expr, fallback: true)
40
40
  matched = false
41
41
  expr.to_s.split(',').each do |name|
42
42
  name.strip!
@@ -50,22 +50,25 @@ module ActiveRecord # :nodoc:
50
50
  field = _fields[name]
51
51
  next unless field
52
52
 
53
- matched = true
53
+ matched = true
54
54
  relation = field.order(relation, rank)
55
55
  end
56
56
 
57
- relation = order(relation, _default, false) if fallback && !matched && _default
57
+ relation = order(relation, _default, fallback: false) if fallback && !matched && _default
58
58
  relation
59
59
  end
60
60
  end
61
61
 
62
62
  class Field # :nodoc:
63
- def initialize(name, opts = {})
64
- @cols = Array.wrap(opts[:as])
65
- @eager_load = Array.wrap(opts[:eager_load]).presence
63
+ STRING_TYPES = %i[string text].freeze # :nodoc:
64
+
65
+ def initialize(name, as: nil, scope: nil, eager_load: nil, case_sensitive: false)
66
+ @cols = Array.wrap(as)
67
+ @eager_load = Array.wrap(eager_load).presence
68
+ @case_sensitive = case_sensitive == true
66
69
 
67
70
  # validate custom_scope
68
- @custom_scope = opts[:scope]
71
+ @custom_scope = scope
69
72
  raise ArgumentError, "Invalid sortable-by field '#{name}': scope must be a Proc." if @custom_scope && !@custom_scope.is_a?(Proc)
70
73
 
71
74
  # normalize cols
@@ -86,7 +89,10 @@ module ActiveRecord # :nodoc:
86
89
  @cols.each do |col|
87
90
  case col
88
91
  when String, Symbol
89
- relation = relation.order(col => rank)
92
+ type = relation.columns_hash[col.to_s].type
93
+ col = relation.arel_table[col]
94
+ col = col.lower if STRING_TYPES.include?(type) && !@case_sensitive
95
+ relation = relation.order(col.send(rank))
90
96
  when Arel::Nodes::Node, Arel::Attributes::Attribute
91
97
  relation = relation.order(col.send(rank))
92
98
  when Proc
@@ -117,10 +123,10 @@ module ActiveRecord # :nodoc:
117
123
  # sortable_by :title, :id
118
124
  # end
119
125
  #
120
- # # Case-insensitive
126
+ # # Case-sensitive
121
127
  # class Post < ActiveRecord::Base
122
128
  # sortable_by do |x|
123
- # x.field :title, as: arel_table[:title].lower
129
+ # x.field :title, case_sensitive: true
124
130
  # x.field :id
125
131
  # end
126
132
  # end
@@ -144,7 +150,7 @@ module ActiveRecord # :nodoc:
144
150
  #
145
151
  # sortable_by do |x|
146
152
  # x.field :name
147
- # x.field :shop, as: Shop.arel_table[:name].lower, eager_load: :shop
153
+ # x.field :shop, as: Shop.arel_table[:name], eager_load: :shop
148
154
  # x.default 'shop,name'
149
155
  # end
150
156
  # end
@@ -154,17 +160,16 @@ module ActiveRecord # :nodoc:
154
160
  # belongs_to :shop
155
161
  #
156
162
  # sortable_by do |x|
157
- # x.field :shop, as: Shop.arel_table[:name].lower, scope: -> { joins(:shop) }
163
+ # x.field :shop, as: Shop.arel_table[:name], scope: -> { joins(:shop) }
158
164
  # end
159
165
  # end
160
166
  #
161
- def sortable_by(*attributes)
167
+ def sortable_by(*attributes, **opts)
162
168
  config = _sortable_by_config
163
- opts = attributes.extract_options!
164
169
  default = opts.delete(:default)
165
170
 
166
171
  attributes.each do |name|
167
- config.field(name, opts)
172
+ config.field(name, **opts)
168
173
  end
169
174
  config.default(default) if default
170
175
  yield config if block_given?
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'sortable-by'
3
- s.version = '0.12.1'
3
+ s.version = '0.13.0'
4
4
  s.authors = ['Dimitrij Denissenko']
5
5
  s.email = ['dimitrij@blacksquaremedia.com']
6
6
  s.summary = 'Generate white-listed sort scopes from URL parameter values'
@@ -17,14 +17,14 @@ ActiveRecord::Base.connection.create_table :posts do |t|
17
17
  end
18
18
 
19
19
  class Post < ActiveRecord::Base
20
- sortable_by :title, default: '-created' do |s|
20
+ sortable_by :title, default: '-created', case_sensitive: true do |s|
21
21
  s.field :created, as: arel_table[:created_at]
22
22
  end
23
23
  end
24
24
 
25
25
  class SubPost < Post
26
26
  sortable_by do |s|
27
- s.field :title, as: arel_table[:title].lower
27
+ s.field :title
28
28
  end
29
29
  end
30
30
 
@@ -65,8 +65,8 @@ class Product < ActiveRecord::Base
65
65
  belongs_to :shop
66
66
 
67
67
  sortable_by do |s|
68
- s.field :name, as: arel_table[:name].lower
69
- s.field :shop, as: Shop.arel_table[:name].lower, eager_load: :shop
68
+ s.field :name
69
+ s.field :shop, as: Shop.arel_table[:name], eager_load: :shop
70
70
  s.default 'shop,name'
71
71
  end
72
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sortable-by
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-27 00:00:00.000000000 Z
11
+ date: 2020-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord