sort_param 0.1.0 → 0.2.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/CHANGELOG.md +4 -1
- data/README.md +74 -5
- data/lib/sort_param/definition.rb +3 -2
- data/lib/sort_param/field.rb +2 -2
- data/lib/sort_param/formatters/formatter.rb +8 -0
- data/lib/sort_param/formatters/hash.rb +9 -5
- data/lib/sort_param/formatters/mysql.rb +1 -1
- data/lib/sort_param/formatters/pg.rb +1 -2
- data/lib/sort_param/utilities.rb +15 -5
- data/lib/sort_param/version.rb +1 -1
- 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: c05d893490a180c3cb1ce696d8fbddf77f9e7a0f323434c755408f54f239c427
|
4
|
+
data.tar.gz: 672ae31570afece8e8a18c504f7bbe47390d83c8e7485934edb473ace88e11db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0dbaff8fc1c00aa5903ab1e75576b6af6d99ba37a3d90d41d8a2ef1ed4928d183a278d31552924aa94ba2aa0b395639d176a477cc50a0ed9379e61cc069c2ddb
|
7
|
+
data.tar.gz: fe8ca1f676f8f4ff66a5e3a9395457218725eb440b37f1ee253752a5f77a1ae761e79136521735c0b291f92f54e6e3c02ec6e7416d3baa1a79840498c3e78c85
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,31 @@
|
|
1
1
|
# SortParam
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/sort_param) [](https://github.com/jsonb-uy/sort_param/actions/workflows/ruby.yml) [](https://codecov.io/gh/jsonb-uy/sort_param) [](https://codeclimate.com/github/jsonb-uy/sort_param/maintainability)
|
4
|
+
|
5
|
+
Sort records using a query parameter based on JSON API's sort parameter format.
|
6
|
+
|
7
|
+
In a nutshell, this gem converts comma-separated sort fields from this:
|
8
|
+
<pre>
|
9
|
+
?sort=<b>+users.first_name,-users.last_name:nulls_last,users.email</b>
|
10
|
+
</pre>
|
11
|
+
|
12
|
+
|
13
|
+
to this:
|
14
|
+
```SQL
|
15
|
+
users.first_name asc, users.last_name desc nulls last, users.email asc
|
16
|
+
```
|
17
|
+
|
18
|
+
or to this:
|
19
|
+
```ruby
|
20
|
+
{"users.first_name"=>{:direction=>:asc}, "users.last_name"=>{:direction=>:desc, :nulls=>:last}, "users.email"=>{:direction=>:asc}}
|
21
|
+
```
|
4
22
|
|
5
23
|
## Features
|
6
24
|
|
25
|
+
* Sort field whitelisting.
|
7
26
|
* Supports `ORDER BY` expression generation for MySQL and PG.
|
8
|
-
*
|
27
|
+
* Parsing of comma-separated sort fields into hash for any further processing.
|
28
|
+
* Specifying `NULL` sort order.
|
9
29
|
|
10
30
|
## Installation
|
11
31
|
|
@@ -80,6 +100,21 @@ sort_param.load!("+first_name,-last_name")
|
|
80
100
|
=> {"first_name"=>{:nulls=>:first, :direction=>:asc}, "last_name"=>{:direction=>:desc}}
|
81
101
|
```
|
82
102
|
|
103
|
+
Any other additional column option set in `SortParam::Definition` or `SortParam.define` will be included in the column's hash value.
|
104
|
+
For example:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
sort_param = SortParam.define do
|
108
|
+
field :first_name, foo: :bar, nulls: :first
|
109
|
+
end
|
110
|
+
|
111
|
+
sort_param.load!("+first_name")
|
112
|
+
=> {"first_name"=>{:foo=>:bar, :nulls=>:first, :direction=>:asc}}
|
113
|
+
|
114
|
+
sort_param.load!("-first_name:nulls_last")
|
115
|
+
=> {"first_name"=>{:foo=>:bar, :nulls=>:last, :direction=>:desc}}
|
116
|
+
```
|
117
|
+
|
83
118
|
#### IV. Example with explicit nulls sort order
|
84
119
|
|
85
120
|
###### Example in PG mode:
|
@@ -94,13 +129,13 @@ sort_param.load!("+first_name:nulls_last,-last_name:nulls_first", mode: :pg)
|
|
94
129
|
### Rails example
|
95
130
|
|
96
131
|
```ruby
|
97
|
-
def index
|
98
|
-
|
132
|
+
def index
|
133
|
+
render json: User.all.order(sort_fields)
|
99
134
|
end
|
100
135
|
|
101
136
|
private
|
102
137
|
|
103
|
-
def
|
138
|
+
def sort_fields
|
104
139
|
SortParam.define do
|
105
140
|
field :first_name
|
106
141
|
field :last_name, nulls: :first
|
@@ -114,6 +149,40 @@ def sort_param
|
|
114
149
|
end
|
115
150
|
```
|
116
151
|
|
152
|
+
We can DRY this up a bit by creating a concern:
|
153
|
+
|
154
|
+
#### controllers/concerns/has_sort_param.rb
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
module HasSortParam
|
158
|
+
extend ActiveSupport::Concern
|
159
|
+
|
160
|
+
def sort_param(default: nil, &block)
|
161
|
+
raise ArgumentError.new('Missing block') unless block_given?
|
162
|
+
|
163
|
+
definition = SortParam.define(&block)
|
164
|
+
definition.load!(params[:sort].presence || default, mode: :pg)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
### controller
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
def index
|
173
|
+
render json: User.all.order(sort_fields)
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def sort_fields
|
179
|
+
sort_param default: '+first_name,-last_name' do
|
180
|
+
field :first_name
|
181
|
+
field :last_name, nulls: :first
|
182
|
+
end
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
117
186
|
### Error
|
118
187
|
|
119
188
|
| Class | Description |
|
@@ -26,6 +26,7 @@ module SortParam
|
|
26
26
|
# @param name [String, Symbol] column name
|
27
27
|
# @param defaults [Hash] column default options:
|
28
28
|
# * nulls (Symbol) nulls sort order. `:last` or `:first`
|
29
|
+
# * formatted_name (String) field name in formatted output
|
29
30
|
#
|
30
31
|
# @return [self] Definition instance
|
31
32
|
def field(name, defaults = {})
|
@@ -52,8 +53,8 @@ module SortParam
|
|
52
53
|
#
|
53
54
|
# @param sort_string [String] Sort expression. Comma-separated sort fields.
|
54
55
|
# @param mode [Symbol, NilClass] Translation format
|
55
|
-
# * `:pg` for PostgreSQL ORDER BY SQL
|
56
|
-
# * `:mysql` for MySQL ORDER BY SQL
|
56
|
+
# * `:pg` for PostgreSQL ORDER BY SQL.
|
57
|
+
# * `:mysql` for MySQL ORDER BY SQL.
|
57
58
|
# * `:hash`/nil for the default hash representation.
|
58
59
|
#
|
59
60
|
# @example Sort by first_name ASC and then by last_name DESC
|
data/lib/sort_param/field.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module SortParam
|
4
4
|
module Formatters
|
5
5
|
class Formatter
|
6
|
+
include Utilities
|
7
|
+
|
6
8
|
def self.for(mode)
|
7
9
|
return Formatters::PG if mode == :pg
|
8
10
|
return Formatters::MySQL if mode == :mysql
|
@@ -34,6 +36,12 @@ module SortParam
|
|
34
36
|
def format_field(field)
|
35
37
|
raise NotImplementedError
|
36
38
|
end
|
39
|
+
|
40
|
+
def formatted_field_name(field)
|
41
|
+
formatted_name = definition.field_defaults(field.name)[:formatted_name]
|
42
|
+
|
43
|
+
blank?(formatted_name) ? field.name : formatted_name
|
44
|
+
end
|
37
45
|
end
|
38
46
|
end
|
39
47
|
end
|
@@ -6,17 +6,21 @@ module SortParam
|
|
6
6
|
private
|
7
7
|
|
8
8
|
def format_field(field)
|
9
|
-
|
10
|
-
field_data.merge!(direction: field.direction)
|
11
|
-
field_data.merge!(nulls: field.nulls) unless field.nulls.nil?
|
12
|
-
|
13
|
-
{ field.name => field_data }
|
9
|
+
{ formatted_field_name(field) => field_data(field) }
|
14
10
|
end
|
15
11
|
|
16
12
|
def format_collection(fields)
|
17
13
|
fields.map { |field| format(field) }
|
18
14
|
.inject(&:merge!)
|
19
15
|
end
|
16
|
+
|
17
|
+
def field_data(field)
|
18
|
+
data = definition.field_defaults(field.name) || {}
|
19
|
+
data.merge!(direction: field.direction)
|
20
|
+
data.merge!(nulls: field.nulls) unless field.nulls.nil?
|
21
|
+
data.delete(:formatted_name)
|
22
|
+
data
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
@@ -11,8 +11,8 @@ module SortParam
|
|
11
11
|
|
12
12
|
def format_field(field)
|
13
13
|
field_defaults = definition.field_defaults(field.name) || {}
|
14
|
-
column_name = field_defaults[:column_name] || field.name
|
15
14
|
|
15
|
+
column_name = formatted_field_name(field)
|
16
16
|
nulls = (field.nulls || field_defaults[:nulls]).to_s
|
17
17
|
nulls_sort_order = nulls_order(column_name, nulls)
|
18
18
|
return "#{column_name} #{field.direction}" if nulls_sort_order.nil?
|
@@ -11,10 +11,9 @@ module SortParam
|
|
11
11
|
|
12
12
|
def format_field(field)
|
13
13
|
field_defaults = definition.field_defaults(field.name) || {}
|
14
|
-
column_name = field_defaults[:column_name] || field.name
|
15
14
|
|
16
15
|
nulls = (field.nulls || field_defaults[:nulls]).to_s
|
17
|
-
"#{
|
16
|
+
"#{formatted_field_name(field)} #{field.direction}#{nulls_order(nulls)}"
|
18
17
|
end
|
19
18
|
|
20
19
|
def nulls_order(nulls)
|
data/lib/sort_param/utilities.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
module SortParam
|
2
2
|
module Utilities
|
3
|
-
def
|
4
|
-
|
5
|
-
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def blank?(str)
|
9
|
+
return true if str.nil? || str == ""
|
10
|
+
return false unless str.is_a?(String)
|
6
11
|
|
7
|
-
|
8
|
-
|
12
|
+
str.strip!
|
13
|
+
str.empty?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def blank?(str)
|
18
|
+
self.class.blank?(str)
|
9
19
|
end
|
10
20
|
end
|
11
21
|
end
|
data/lib/sort_param/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sort_param
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uy Jayson B
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Sort records using a sort query parameter à la JSON-API style
|
14
14
|
email:
|