sortable-by 0.12.1 → 0.13.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/.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
|