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 +4 -4
- data/.rubocop.yml +2 -0
- data/.travis.yml +1 -0
- data/Gemfile.lock +25 -23
- data/README.md +12 -12
- data/lib/sortable_by.rb +22 -17
- data/sortable-by.gemspec +1 -1
- data/spec/spec_helper.rb +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4639f942b5f628b07367a343160d7e4301b00bf3c6e0db9f57ff43d204a85ab5
|
4
|
+
data.tar.gz: 2f424ec2cda37112ca64fdf628b7ff0aee3e223dbee81d585040eff79ee468c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff08a62e083e324f9baa4118423c82d90ad93d00f42b4cd6ae74d915a637439315f4cf5ebd8b9d598075bd9565064429a06d0017bae3b5f7998c35b39a50f14c
|
7
|
+
data.tar.gz: b084242394054b896d594c923e262c6325a74c58c836e2224ee5c4f91c3bc087bedfe0b42eb7aa2438ea2a84dd41ddd54c6b5718f68e181d5869bbb5efcb2397
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,41 +1,42 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sortable-by (0.
|
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.
|
12
|
-
activesupport (= 6.0.3.
|
13
|
-
activerecord (6.0.3.
|
14
|
-
activemodel (= 6.0.3.
|
15
|
-
activesupport (= 6.0.3.
|
16
|
-
activesupport (6.0.3.
|
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.
|
23
|
-
concurrent-ruby (1.1.
|
24
|
-
diff-lcs (1.
|
25
|
-
i18n (1.8.
|
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.
|
28
|
-
parallel (1.19.
|
29
|
-
parser (2.7.
|
30
|
-
ast (~> 2.4.
|
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.
|
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.
|
48
|
+
rubocop (0.92.0)
|
48
49
|
parallel (~> 1.10)
|
49
|
-
parser (>= 2.7.
|
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
|
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.
|
56
|
-
parser (>= 2.7.
|
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.
|
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.
|
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-
|
29
|
+
Case-sensitive:
|
30
30
|
|
31
31
|
```ruby
|
32
32
|
class Post < ActiveRecord::Base
|
33
33
|
sortable_by do |x|
|
34
|
-
x.field :title,
|
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
|
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
|
72
|
-
x.field :shop, as: Shop.arel_table[:name]
|
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]
|
84
|
+
x.field :shop, as: Shop.arel_table[:name], scope: -> { joins(:shop) }
|
85
85
|
end
|
86
86
|
end
|
87
87
|
```
|
data/lib/sortable_by.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
64
|
-
|
65
|
-
|
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 =
|
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
|
-
|
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-
|
126
|
+
# # Case-sensitive
|
121
127
|
# class Post < ActiveRecord::Base
|
122
128
|
# sortable_by do |x|
|
123
|
-
# x.field :title,
|
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]
|
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]
|
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?
|
data/sortable-by.gemspec
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -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
|
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
|
69
|
-
s.field :shop, as: Shop.arel_table[:name]
|
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.
|
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-
|
11
|
+
date: 2020-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|