sort_param 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78cff5e96b34b0697aa50227db7186cbbbaac54290cdaf88ff6201ae35afda6e
4
- data.tar.gz: 025b26afa452522750032d2be80f83dca0c0343ff00416e2a6d2299e47680980
3
+ metadata.gz: 410b605717d78b03414a2efa8fe9bcfc7db220f52b68ec20526068ee214dd695
4
+ data.tar.gz: 7b472ee03998faf9e05fb5aebb4a39e36d2a06853169598a9089a48cd04bf93a
5
5
  SHA512:
6
- metadata.gz: 8c191c86a31f9a9c300ab3064d3b44b9be8f273fc4578de139482f7434bb07b5c69d44ef12077b262a2832757450f7ded50ced460e501cf602328a29e6e2d2ad
7
- data.tar.gz: 788302acfbcf086d426fe2adebb1c5ee59aa85ece7e5e78e956e6ea81987b04efef002ed052d7b0615736648b17552a46c7a5d85c44e94a2f0d6f416ebf4b94e
6
+ metadata.gz: 2ad6f2f434973f1b1c25ce86d9949f02443a042ecc1a7279eb208c3eecfb04410adbcb0ea436b0341d729747c17665a8d7b25a9fb6d181f4d3623933b90e7a40
7
+ data.tar.gz: f838dd76a5d4e8231c6308f33575dae253c5cd4ab6f6e887488b3ab74da6252ee39ed4b3beb77e024c3f503e358a659788ee62ae78eeb6041f4049881a814ce2
data/CHANGELOG.md CHANGED
@@ -6,3 +6,11 @@
6
6
 
7
7
  ## [1.0.0]
8
8
  - Rename :formatted_name option to :rename
9
+
10
+ ## [1.1.0]
11
+ - Introduce definition#load to silently ignore non-whitelisted sort fields
12
+
13
+ ## [1.2.0]
14
+ - Introduce #fields to whitelist multiple fields with the same field defaults at once
15
+ - Allow field renaming using a Proc instead of hardcoding a string value
16
+
data/README.md CHANGED
@@ -124,14 +124,26 @@ sort_param.load!("+first_name:nulls_last,-last_name:nulls_first", mode: :pg)
124
124
 
125
125
  => "first_name asc nulls last, last_name desc nulls first"
126
126
  ```
127
- <br/>
128
127
 
129
- ### Render a different field name in the output
130
- Set the `:rename` field option to output a different field name:
128
+ ### Ignoring non-whitelisted sort fields instead of raising error
129
+ Use `#load` method instead:
130
+
131
+ ```ruby
132
+ sort_param = SortParam.define do
133
+ field :first_name
134
+ end
135
+
136
+ sort_param.load("+first_name,+last_name", mode: :pg)
137
+ => "first_name asc"
138
+ ```
139
+
140
+ ### Output a different field name
141
+ Set the `:rename` field option to a string value or a Proc to output a different field name.
131
142
 
132
143
  ```ruby
133
144
  sort_param = SortParam.define do
134
145
  field :first_name, rename: 'users.name'
146
+ field :last_name, rename: ->(col) { "users.#{col}" }
135
147
  end
136
148
 
137
149
  sort_param.load!("+first_name", mode: :pg)
@@ -142,12 +154,28 @@ Set the `:rename` field option to output a different field name:
142
154
 
143
155
  sort_param.load!("+first_name")
144
156
  => {"users.name"=>{:direction=>:asc}}
157
+
158
+ sort_param.load!("+last_name")
159
+ => {"users.last_name"=>{:direction=>:asc}}
145
160
  ```
146
161
 
147
- <br/>
162
+ ### Whitelisting multiple fields with the same options at once
163
+ Use `#fields` instead of `#field`:
164
+
165
+ ```ruby
166
+ sort_param = SortParam.define do
167
+ fields :first_name, :last_name, nulls: :first, rename: ->(col) { "users.#{col}" }
168
+ field :email
169
+ end
170
+ ```
171
+
172
+ NOTE: Unlike `#field`, `#fields` can only accept a Proc for the `:rename` option.
173
+
148
174
 
149
175
  ### Rails example
150
176
 
177
+ ### controller
178
+
151
179
  ```ruby
152
180
  def index
153
181
  render json: User.all.order(sort_fields)
@@ -186,7 +214,7 @@ module HasSortParam
186
214
  end
187
215
  ```
188
216
 
189
- ### controller
217
+ ### controller v2
190
218
 
191
219
  ```ruby
192
220
  def index
@@ -207,7 +235,7 @@ end
207
235
 
208
236
  | Class | Description |
209
237
  | ----------- | ----------- |
210
- | `SortParam::UnsupportedSortField` | Raised when a sort field from the parameter isn't included in the whitelisted sort fields. |
238
+ | `SortParam::UnsupportedSortField` | Raised when loading sort string via `#load!` and a sort field from the parameter isn't included in the whitelisted sort fields. |
211
239
 
212
240
  ## Development
213
241
 
@@ -21,19 +21,40 @@ module SortParam
21
21
  self
22
22
  end
23
23
 
24
- # Add a whitelisted column
24
+ # Whitelist a column
25
25
  #
26
26
  # @param name [String, Symbol] column name
27
27
  # @param defaults [Hash] column default options:
28
- # * nulls (Symbol) nulls sort order. `:last` or `:first`
29
- # * rename (String) field name in formatted output
28
+ # * nulls [Symbol] nulls sort order. `:last` or `:first`
29
+ # * rename [String, Proc] rename field in the formatted output.
30
+ # This can be a Proc code block that receives the :name as argument and
31
+ # returns a transformed field name.
30
32
  #
31
33
  # @return [self] Definition instance
32
- def field(name, defaults = {})
34
+ def field(name, **defaults)
33
35
  name = name.to_s
34
36
  return if name.strip.empty?
35
37
 
36
- fields_hash[name] = defaults
38
+ fields_hash[name] = preprocess_field_defaults(name, defaults)
39
+
40
+ self
41
+ end
42
+
43
+ # Whitelist multiple columns with the same column defaults.
44
+ #
45
+ # @param name [Array<String, Symbol>] list of column names
46
+ # @param defaults [Hash] column default options
47
+ #
48
+ # @see #field
49
+ #
50
+ # @return [self] Definition instance
51
+ #
52
+ def fields(*names, **defaults)
53
+ if defaults[:rename] && !defaults[:rename].is_a?(Proc)
54
+ raise ArgumentError.new(":rename should be a Proc")
55
+ end
56
+
57
+ names.each { |name| field(name, **defaults) }
37
58
 
38
59
  self
39
60
  end
@@ -49,6 +70,20 @@ module SortParam
49
70
  @fields_hash[name].dup
50
71
  end
51
72
 
73
+ # Parse then translate a sort string expression and raise an error if the sort string includes
74
+ # a non-whitelisted sort field.
75
+ #
76
+ # @see #load
77
+ #
78
+ # @raise [SortParam::UnsupportedSortField] if :sort_string includes a non-whitelisted sort field.
79
+ #
80
+ def load!(sort_string, mode: :hash)
81
+ fields = Fields.new(sort_string)
82
+ validate_fields!(fields)
83
+
84
+ format_fields(mode, fields)
85
+ end
86
+
52
87
  # Parse then translate a sort string expression
53
88
  #
54
89
  # @param sort_string [String] Sort expression. Comma-separated sort fields.
@@ -71,18 +106,35 @@ module SortParam
71
106
  # @return [Hash, String, NilClass] Translated to SQL or Hash.
72
107
  # Returns nil if there is no column to sort.
73
108
  #
74
- def load!(sort_string, mode: :hash)
109
+ def load(sort_string, mode: :hash)
75
110
  fields = Fields.new(sort_string)
76
- validate_fields!(fields)
111
+ fields = fields.reject { |field| non_whitelisted_fields(fields).include?(field.name) }
77
112
 
78
- formatter = Formatters::Formatter.for(mode)
79
- formatter.new(self).format(*fields)
113
+ format_fields(mode, fields)
80
114
  end
81
115
 
82
116
  private
83
117
 
84
- def validate_fields!(fields)
85
- unknown_field = (fields.names - fields_hash.keys).first
118
+ def format_fields(mode, fields)
119
+ Formatters::Formatter.for(mode)
120
+ .new(self)
121
+ .format(*fields)
122
+ end
123
+
124
+ def preprocess_field_defaults(field, defaults)
125
+ rename = defaults[:rename]
126
+ return defaults unless rename.is_a?(Proc)
127
+
128
+ defaults[:rename] = defaults[:rename].call(field)
129
+ defaults
130
+ end
131
+
132
+ def non_whitelisted_fields(loaded_fields)
133
+ loaded_fields.names - fields_hash.keys
134
+ end
135
+
136
+ def validate_fields!(loaded_fields)
137
+ unknown_field = non_whitelisted_fields(loaded_fields).first
86
138
  return true if unknown_field.nil?
87
139
 
88
140
  raise SortParam::UnsupportedSortField.new("Unsupported sort field: #{unknown_field}")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SortParam
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sort_param
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.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-14 00:00:00.000000000 Z
11
+ date: 2023-06-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Sort records using a sort query parameter à la JSON-API style
13
+ description: Sort records using a sort query parameter à la JSON:API format
14
14
  email:
15
15
  - uy.json.dev@gmail.com
16
16
  executables: []
@@ -57,5 +57,5 @@ requirements: []
57
57
  rubygems_version: 3.4.6
58
58
  signing_key:
59
59
  specification_version: 4
60
- summary: Sort records using a sort query parameter à la JSON-API style
60
+ summary: Sort records using a sort query parameter à la JSON:API format
61
61
  test_files: []