normalizy 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 +11 -0
- data/README.md +379 -32
- data/lib/normalizy/config.rb +7 -3
- data/lib/normalizy/extensions.rb +11 -7
- data/lib/normalizy/filters/date.rb +44 -0
- data/lib/normalizy/filters/money.rb +38 -0
- data/lib/normalizy/filters/number.rb +4 -3
- data/lib/normalizy/filters/percent.rb +38 -0
- data/lib/normalizy/rspec/matcher.rb +2 -0
- data/lib/normalizy/version.rb +1 -1
- data/spec/normalizy/config/add_spec.rb +3 -0
- data/spec/normalizy/config/alias_spec.rb +7 -13
- data/spec/normalizy/config/initialize_spec.rb +5 -2
- data/spec/normalizy/config/normalizy_raws_spec.rb +1 -1
- data/spec/normalizy/extensions/{apply_normalizations_spec.rb → apply_normalizy_spec.rb} +36 -28
- data/spec/normalizy/extensions/filters/date_spec.rb +34 -0
- data/spec/normalizy/extensions/filters/money_spec.rb +40 -0
- data/spec/normalizy/extensions/filters/number_spec.rb +13 -0
- data/spec/normalizy/extensions/filters/percent_spec.rb +40 -0
- data/spec/normalizy/extensions/filters/strip_spec.rb +21 -0
- data/spec/normalizy/extensions/normalizy_rules_spec.rb +1 -1
- data/spec/normalizy/filters/date_spec.rb +56 -0
- data/spec/normalizy/filters/money_spec.rb +155 -0
- data/spec/normalizy/filters/number_spec.rb +25 -9
- data/spec/normalizy/filters/percent_spec.rb +155 -0
- data/spec/rails_helper.rb +4 -0
- data/spec/support/db/schema.rb +8 -3
- data/spec/support/filters/blacklist_1.rb +11 -0
- data/spec/support/filters/blacklist_2.rb +13 -0
- data/spec/support/filters/blacklist_block.rb +11 -0
- data/spec/support/models/user.rb +1 -1
- metadata +29 -8
- data/spec/normalizy/extensions/normalizy_spec.rb +0 -11
- data/spec/support/filters/blacklist_filter.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76436253c67c497cba120a39bd71667b34cad65f
|
4
|
+
data.tar.gz: c5bb1d390b33e655ea7e5e9c865cf4bf8d903fc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 488852bd2f5c2ce038533f7dcd984b537b5e27cd185cccafa560553cf7f50a13d8a7bac0e15670c6647fff376957b91a53463b966713f887ed5e566f68d32415
|
7
|
+
data.tar.gz: 7205c44545020100f4663e2ca7e9d9af224dfda0e3bb6645acee7defb8798c76bec57582678a25670a5f4c07d2f6d07fed151d089e81f72e154ca6fd20afb806
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## v0.2.0
|
2
|
+
|
3
|
+
- Changes:
|
4
|
+
- `number` filter no more make cast automatically.
|
5
|
+
- `number` now accept `cast` options with method to be used on cast type;
|
6
|
+
|
7
|
+
- Features:
|
8
|
+
- add `date` filter with `format`, `time_zone` and I18n error message support;
|
9
|
+
- add `money` filter with `cast`, `type` and I18n support;
|
10
|
+
- add `percent` filter with `cast`, `type` and I18n support.
|
11
|
+
|
1
12
|
## v0.1.0
|
2
13
|
|
3
14
|
- First release.
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ Attribute normalizer for ActiveRecord.
|
|
7
7
|
|
8
8
|
## Description
|
9
9
|
|
10
|
-
If you know the obvious format of an input, why not normalize it instead of raise an validation error to your use? Make the follow email `
|
10
|
+
If you know the obvious format of an input, why not normalize it instead of raise an validation error to your use? Make the follow email ` Email@example.com ` valid like `email@example.com` with no need to override acessors methods.
|
11
11
|
|
12
12
|
## install
|
13
13
|
|
@@ -35,22 +35,319 @@ class User < ApplicationRecord
|
|
35
35
|
end
|
36
36
|
```
|
37
37
|
|
38
|
-
Now some email like ` myemail@example.
|
38
|
+
Now some email like ` myemail@example.com ` will be saved as `email@example.com`.
|
39
39
|
|
40
40
|
## Filters
|
41
41
|
|
42
|
-
We have a couple of built-in filters.
|
42
|
+
We have a couple of built-in filters.
|
43
|
+
|
44
|
+
### Date
|
45
|
+
|
46
|
+
Transform a value to date format.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
normalizy :birthday, with: :date
|
50
|
+
|
51
|
+
'1984-10-23'
|
52
|
+
# Tue, 23 Oct 1984 00:00:00 UTC +00:00
|
53
|
+
```
|
54
|
+
|
55
|
+
By default, the date is treat as `%F` format and as `UTC` time.
|
56
|
+
|
57
|
+
#### format
|
58
|
+
|
59
|
+
You can change the format using the `format` options:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
normalizy :birthday, with: date: { format: '%y/%m/%d' }
|
63
|
+
|
64
|
+
'84/10/23'
|
65
|
+
# Tue, 23 Oct 1984 00:00:00 UTC +00:00
|
66
|
+
```
|
67
|
+
|
68
|
+
#### time zone
|
69
|
+
|
70
|
+
To convert the date on your time zone, just provide the `time_zone` option:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
normalizy :birthday, with: date: { time_zone: '%y/%m/%d' }
|
74
|
+
|
75
|
+
'1984-10-23'
|
76
|
+
# Tue, 23 Oct 1984 00:00:00 EDT -04:00
|
77
|
+
```
|
78
|
+
|
79
|
+
#### error message
|
80
|
+
|
81
|
+
If an invalid date is provided, Normalizy will add an error on attribute of the related object.
|
82
|
+
You can customize the error via I18n config:
|
83
|
+
|
84
|
+
```yml
|
85
|
+
en:
|
86
|
+
normalizy:
|
87
|
+
errors:
|
88
|
+
date:
|
89
|
+
user:
|
90
|
+
birthday: '%{value} is an invalid date.'
|
91
|
+
```
|
92
|
+
|
93
|
+
If no configuration is provided, the default message will be `'%{value} is an invalid date.`.
|
94
|
+
|
95
|
+
#### adjust
|
96
|
+
|
97
|
+
If your model receive a `Time` or `DateTime`, you can provide `adjust` options to change you time to begin o the day:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
normalizy :birthday, with: date: { adjust: :begin }
|
101
|
+
|
102
|
+
Tue, 23 Oct 1984 11:30:00 EDT -04:00
|
103
|
+
# Tue, 23 Oct 1984 00:00:00 EDT -04:00
|
104
|
+
```
|
105
|
+
|
106
|
+
Or to the end of the day:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
normalizy :birthday, with: date: { adjust: :end }
|
110
|
+
|
111
|
+
Tue, 23 Oct 1984 00:00:00 EDT -04:00
|
112
|
+
# Tue, 23 Oct 1984 11:59:59 EDT -04:00
|
113
|
+
```
|
114
|
+
|
115
|
+
By default, `number` works with value before [Type Cast](#type-cast).
|
116
|
+
|
117
|
+
### Money
|
118
|
+
|
119
|
+
Transform a value to money format.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
normalizy :amount, with: :money
|
123
|
+
|
124
|
+
'$ 42.00'
|
125
|
+
# '42.00'
|
126
|
+
```
|
127
|
+
|
128
|
+
#### separator
|
129
|
+
|
130
|
+
The `separator` will be keeped on value to be possible cast the right integer value.
|
131
|
+
You can change this separator:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
normalizy :amount, with: money: { separator: ',' }
|
135
|
+
|
136
|
+
'R$ 42,00'
|
137
|
+
# '42,00'
|
138
|
+
```
|
139
|
+
|
140
|
+
If you do not want pass it as options, Normalizy will fetch your I18n config:
|
141
|
+
|
142
|
+
```yaml
|
143
|
+
en:
|
144
|
+
currency:
|
145
|
+
format:
|
146
|
+
separator: '.'
|
147
|
+
```
|
148
|
+
|
149
|
+
And if it does not exists, `.` will be used as default.
|
150
|
+
|
151
|
+
#### type
|
152
|
+
|
153
|
+
You can retrieve the value in *cents* format, use the `type` options as `cents`:
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
normalizy :amount, with: money: { type: :cents }
|
157
|
+
|
158
|
+
'$ 42.00'
|
159
|
+
# '4200'
|
160
|
+
```
|
161
|
+
|
162
|
+
#### precision
|
163
|
+
|
164
|
+
As you could see on the last example, when using `type: :cents` is important the number of decimal digits.
|
165
|
+
So, you can configure it to avoid the following error:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
normalizy :amount, with: money: { type: :cents }
|
169
|
+
|
170
|
+
'$ 42.0'
|
171
|
+
# 420
|
172
|
+
```
|
173
|
+
|
174
|
+
When you parse it back, the value need to be divided by `100` to be presented, but it will result in a value you do not want: `4.2` instead of the original `42.0`. Just provide a `precision`:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
normalizy :amount, with: money: { precision: 2 }
|
178
|
+
|
179
|
+
'$ 42.0'
|
180
|
+
# 42.00
|
181
|
+
```
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
normalizy :amount, with: money: { precision: 2, type: :cents }
|
185
|
+
|
186
|
+
'$ 42.0'
|
187
|
+
# 4200
|
188
|
+
```
|
189
|
+
|
190
|
+
If you do not want pass it as options, Normalizy will fetch your I18n config:
|
191
|
+
|
192
|
+
```yaml
|
193
|
+
en:
|
194
|
+
currency:
|
195
|
+
format:
|
196
|
+
separator: 2
|
197
|
+
```
|
198
|
+
|
199
|
+
And if it does not exists, `2` will be used as default.
|
200
|
+
|
201
|
+
#### cast
|
202
|
+
|
203
|
+
If you need get a number over a normalized string in a number style, provide `cast` option with desired cast method:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
normalizy :amount, with: money: { cast: :to_i }
|
207
|
+
|
208
|
+
'$ 42.00'
|
209
|
+
# 4200
|
210
|
+
```
|
211
|
+
|
212
|
+
Just pay attention to avoid to use `type: :cents` together `cast` with float parses.
|
213
|
+
Since `type` runs first, you will add decimal in a number that already is represented with decimal, but as integer:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
normalizy :amount, with: money: { cast: :to_f, type: :cents }
|
217
|
+
|
218
|
+
'$ 42.00'
|
219
|
+
# 4200.0
|
220
|
+
```
|
221
|
+
|
222
|
+
By default, `money` works with value before [Type Cast](#type-cast).
|
43
223
|
|
44
224
|
### Number
|
45
225
|
|
46
226
|
```ruby
|
47
227
|
normalizy :age, with: :number
|
48
228
|
|
49
|
-
'
|
229
|
+
' 32x'
|
230
|
+
# '32'
|
231
|
+
```
|
232
|
+
|
233
|
+
If you want cast the value, provide `cast` option with desired cast method:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
normalizy :age, with: number: { cast: :to_i }
|
237
|
+
|
238
|
+
' 32x'
|
50
239
|
# 32
|
51
240
|
```
|
52
241
|
|
53
|
-
By default, `number` works with
|
242
|
+
By default, `number` works with value before [Type Cast](#type-cast).
|
243
|
+
|
244
|
+
### Percent
|
245
|
+
|
246
|
+
Transform a value to percent format.
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
normalizy :amount, with: :percent
|
250
|
+
|
251
|
+
'42.00 %'
|
252
|
+
# '42.00'
|
253
|
+
```
|
254
|
+
|
255
|
+
#### separator
|
256
|
+
|
257
|
+
The `separator` will be keeped on value to be possible cast the right integer value.
|
258
|
+
You can change this separator:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
normalizy :amount, with: percent: { separator: ',' }
|
262
|
+
|
263
|
+
'42,00 %'
|
264
|
+
# '42,00'
|
265
|
+
```
|
266
|
+
|
267
|
+
If you do not want pass it as options, Normalizy will fetch your I18n config:
|
268
|
+
|
269
|
+
```yaml
|
270
|
+
en:
|
271
|
+
percentage:
|
272
|
+
format:
|
273
|
+
separator: '.'
|
274
|
+
```
|
275
|
+
|
276
|
+
And if it does not exists, `.` will be used as default.
|
277
|
+
|
278
|
+
#### type
|
279
|
+
|
280
|
+
You can retrieve the value in *integer* format, use the `type` options as `integer`:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
normalizy :amount, with: percent: { type: :integer }
|
284
|
+
|
285
|
+
'42.00 %'
|
286
|
+
# '4200'
|
287
|
+
```
|
288
|
+
|
289
|
+
#### precision
|
290
|
+
|
291
|
+
As you could see on the last example, when using `type: :integer` is important the number of decimal digits.
|
292
|
+
So, you can configure it to avoid the following error:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
normalizy :amount, with: percent: { type: :integer }
|
296
|
+
|
297
|
+
'42.0 %'
|
298
|
+
# 420
|
299
|
+
```
|
300
|
+
|
301
|
+
When you parse it back, the value need to be divided by `100` to be presented, but it will result in a value you do not want: `4.2` instead of the original `42.0`. Just provide a `precision`:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
normalizy :amount, with: percent: { precision: 2 }
|
305
|
+
|
306
|
+
'42.0 %'
|
307
|
+
# 42.00
|
308
|
+
```
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
normalizy :amount, with: percent: { precision: 2, type: :integer }
|
312
|
+
|
313
|
+
'42.0 %'
|
314
|
+
# 4200
|
315
|
+
```
|
316
|
+
|
317
|
+
If you do not want pass it as options, Normalizy will fetch your I18n config:
|
318
|
+
|
319
|
+
```yaml
|
320
|
+
en:
|
321
|
+
percentage:
|
322
|
+
format:
|
323
|
+
separator: 2
|
324
|
+
```
|
325
|
+
|
326
|
+
And if it does not exists, `2` will be used as default.
|
327
|
+
|
328
|
+
#### cast
|
329
|
+
|
330
|
+
If you need get a number over a normalized string in a number style, provide `cast` option with desired cast method:
|
331
|
+
|
332
|
+
```ruby
|
333
|
+
normalizy :amount, with: percent: { cast: :to_i }
|
334
|
+
|
335
|
+
'42.00 %'
|
336
|
+
# 4200
|
337
|
+
```
|
338
|
+
|
339
|
+
Just pay attention to avoid to use `type: :integer` together `cast` with float parses.
|
340
|
+
Since `type` runs first, you will add decimal in a number that already is represented with decimal, but as integer:
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
normalizy :amount, with: percent: { cast: :to_f, type: :integer }
|
344
|
+
|
345
|
+
'42.00 %'
|
346
|
+
# 4200.0
|
347
|
+
```
|
348
|
+
|
349
|
+
By default, `percent` works with value before [Type Cast](#type-cast).
|
350
|
+
|
54
351
|
### Strip
|
55
352
|
|
56
353
|
Options:
|
@@ -101,7 +398,7 @@ You can normalize more than one attribute at once too, with one or muiltiple fil
|
|
101
398
|
normalizy :email, :username, with: :downcase
|
102
399
|
```
|
103
400
|
|
104
|
-
Of course you can declare muiltiples attribute and multiple filters
|
401
|
+
Of course you can declare muiltiples attribute and multiple filters, either.
|
105
402
|
It is possible to make sequential normalizy calls:
|
106
403
|
|
107
404
|
```ruby
|
@@ -113,7 +410,7 @@ In this case, each line will be evaluated from the top to the bottom.
|
|
113
410
|
|
114
411
|
## Default Filters
|
115
412
|
|
116
|
-
You can configure some default filters to be runned. Edit
|
413
|
+
You can configure some default filters to be runned. Edit initializer at `config/initializers/normalizy.rb`:
|
117
414
|
|
118
415
|
```ruby
|
119
416
|
Normalizy.configure do |config|
|
@@ -168,7 +465,9 @@ normalizy :name, with: :blacklist
|
|
168
465
|
# 'Washington *** Botelho'
|
169
466
|
```
|
170
467
|
|
171
|
-
|
468
|
+
#### options
|
469
|
+
|
470
|
+
If you want to pass options to your filter, just call it as a hash and the value will be send to the custom filter:
|
172
471
|
|
173
472
|
```ruby
|
174
473
|
module Normalizy
|
@@ -189,6 +488,13 @@ normalizy :name, with: blacklist: { replacement: '---' }
|
|
189
488
|
# 'Washington --- Botelho'
|
190
489
|
```
|
191
490
|
|
491
|
+
### options value
|
492
|
+
|
493
|
+
By default, Modules and instance methods of class will receveis the following attributes on `options` argument:
|
494
|
+
|
495
|
+
- `object`: The object that Normalizy is acting;
|
496
|
+
- `attribute`: The attribute of the object that Normalizy is acting.
|
497
|
+
|
192
498
|
You can pass a block and it will be received on filter:
|
193
499
|
|
194
500
|
```ruby
|
@@ -214,16 +520,14 @@ normalizy :name, with: :blacklist, &->(value) { value.sub('filtered', '(filtered
|
|
214
520
|
# 'Washington (filtered 2x) Botelho'
|
215
521
|
```
|
216
522
|
|
217
|
-
The block
|
218
|
-
|
219
523
|
## Method Filters
|
220
524
|
|
221
|
-
If a built-in filter is not found, Normalizy will try to find a method
|
525
|
+
If a built-in filter is not found, Normalizy will try to find a method in the current class.
|
222
526
|
|
223
527
|
```ruby
|
224
528
|
normalizy :birthday, with: :parse_date
|
225
529
|
|
226
|
-
def parse_date(input
|
530
|
+
def parse_date(input)
|
227
531
|
Time.zone.parse(input).strftime '%Y/%m/%d'
|
228
532
|
end
|
229
533
|
|
@@ -231,7 +535,7 @@ end
|
|
231
535
|
# '1984/10/23'
|
232
536
|
```
|
233
537
|
|
234
|
-
If you gives an option, it will be passed to the function
|
538
|
+
If you gives an option, it will be passed to the function:
|
235
539
|
|
236
540
|
```ruby
|
237
541
|
normalizy :birthday, with: { parse_date: { format: '%Y/%m/%d' }
|
@@ -244,7 +548,7 @@ end
|
|
244
548
|
# '1984/10/23'
|
245
549
|
```
|
246
550
|
|
247
|
-
Block methods works here
|
551
|
+
Block methods works here either.
|
248
552
|
|
249
553
|
## Native Filter
|
250
554
|
|
@@ -262,7 +566,7 @@ normalizy :name, with: :reverse
|
|
262
566
|
Maybe you want to declare an inline filter, in this case, just use a Lambda or Proc:
|
263
567
|
|
264
568
|
```ruby
|
265
|
-
normalizy :age, with: ->(input) { input.abs }
|
569
|
+
normalizy :age, with: ->(input) { input.to_i.abs }
|
266
570
|
|
267
571
|
-32
|
268
572
|
# 32
|
@@ -272,60 +576,68 @@ You can use it on filters declaration too:
|
|
272
576
|
|
273
577
|
```ruby
|
274
578
|
Normalizy.configure do |config|
|
275
|
-
config.add :age, ->(input) { input.abs }
|
579
|
+
config.add :age, ->(input) { input.to_i.abs }
|
276
580
|
end
|
277
581
|
```
|
278
582
|
|
279
583
|
## Type Cast
|
280
584
|
|
281
|
-
An input field with
|
282
|
-
will be converted to `0`, since the type does not match. But you want to use the value before Rails
|
585
|
+
An input field with `= 42` value when sent to model with a field as `integer` type,
|
586
|
+
will be converted to `0`, since the type does not match. But you want to use the value before Rails cast the type.
|
283
587
|
|
284
588
|
To receive the value before type cast, just pass a `raw` options as `true`:
|
285
589
|
|
286
590
|
```ruby
|
287
591
|
normalizy :amount, with: :number, raw: true
|
288
592
|
|
289
|
-
'
|
290
|
-
#
|
593
|
+
'= 42'
|
594
|
+
# 42
|
291
595
|
```
|
292
596
|
|
293
|
-
To avoid repeat the `raw: true`
|
597
|
+
To avoid repeat the `raw: true` when you have multiple uses, you can register a filter:
|
294
598
|
|
295
599
|
```ruby
|
296
600
|
Normalizy.configure do |config|
|
297
|
-
config.add :
|
601
|
+
config.add :raw_number, ->(input) { input.gsub(/\D/, '') }, raw: true
|
298
602
|
end
|
299
603
|
```
|
300
604
|
|
605
|
+
And use it in short version:
|
606
|
+
|
607
|
+
```ruby
|
608
|
+
normalizy :amount, with: :raw_number
|
609
|
+
|
610
|
+
'= 42'
|
611
|
+
# 42
|
612
|
+
```
|
613
|
+
|
301
614
|
## Alias
|
302
615
|
|
303
616
|
Sometimes you want to give a better name to your filter, just to keep the things semantic.
|
304
|
-
|
617
|
+
Duplicates the code, as you know, is not a good idea, so, create an alias:
|
305
618
|
|
306
619
|
```ruby
|
307
620
|
Normalizy.configure do |config|
|
308
|
-
config.alias :
|
621
|
+
config.alias :age, :number
|
309
622
|
end
|
310
623
|
```
|
311
624
|
|
312
|
-
Now, `
|
313
|
-
Since we already know the need of `raw` options, we can declare it here
|
625
|
+
Now, `age` will delegate to `number` filter.
|
626
|
+
Since we already know the need of `raw` options, we can declare it here:
|
314
627
|
|
315
628
|
```ruby
|
316
629
|
Normalizy.configure do |config|
|
317
|
-
config.alias :
|
630
|
+
config.alias :age, :number, raw: true
|
318
631
|
end
|
319
632
|
```
|
320
633
|
|
321
|
-
|
322
|
-
An our previous example, about `amount`, was refactored to:
|
634
|
+
And now, the aliased filter will work fine:
|
323
635
|
|
324
636
|
```ruby
|
325
|
-
normalizy :
|
637
|
+
normalizy :age, with: :age
|
326
638
|
|
327
|
-
'
|
328
|
-
#
|
639
|
+
'= 42'
|
640
|
+
# 42
|
329
641
|
```
|
330
642
|
|
331
643
|
If you need to alias multiple filters, just provide an array of them:
|
@@ -336,6 +648,41 @@ Normalizy.configure do |config|
|
|
336
648
|
end
|
337
649
|
```
|
338
650
|
|
651
|
+
## RSpec
|
652
|
+
|
653
|
+
If you use [RSpec](http://rspec.info), we did built-in matchers for you.
|
654
|
+
Add the following code to your `rails_helper.rb`
|
655
|
+
|
656
|
+
```ruby
|
657
|
+
RSpec.configure do |config|
|
658
|
+
config.include Normalizy::RSpec
|
659
|
+
end
|
660
|
+
```
|
661
|
+
|
662
|
+
And now you can use some of the matchers:
|
663
|
+
|
664
|
+
##### Result Matcher
|
665
|
+
|
666
|
+
```ruby
|
667
|
+
it { is_expected.to normalizy(:email).from(' Email@example.com ').to 'email@example.com' }
|
668
|
+
```
|
669
|
+
|
670
|
+
##### Filter Matcher
|
671
|
+
|
672
|
+
It will match the given filter literally:
|
673
|
+
|
674
|
+
```ruby
|
675
|
+
it { is_expected.to normalizy(:email).with :downcase }
|
676
|
+
```
|
677
|
+
|
678
|
+
```ruby
|
679
|
+
it { is_expected.to normalizy(:email).with %i[downcase squish] }
|
680
|
+
```
|
681
|
+
|
682
|
+
```ruby
|
683
|
+
it { is_expected.to normalizy(:email).with(trim: { side: :left }) }
|
684
|
+
```
|
685
|
+
|
339
686
|
## Love it!
|
340
687
|
|
341
688
|
Via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=X8HEP2878NDEG&item_name=normalizy) or [Gratipay](https://gratipay.com/~wbotelhos). Thanks! (:
|
data/lib/normalizy/config.rb
CHANGED
@@ -9,6 +9,7 @@ module Normalizy
|
|
9
9
|
|
10
10
|
def add(name, value, raw: false)
|
11
11
|
@filters[name] = value
|
12
|
+
|
12
13
|
@normalizy_raws << name if raw
|
13
14
|
|
14
15
|
self
|
@@ -24,11 +25,14 @@ module Normalizy
|
|
24
25
|
def initialize
|
25
26
|
@default_filters = {}
|
26
27
|
@normalizy_aliases = {}
|
27
|
-
@normalizy_raws = [
|
28
|
+
@normalizy_raws = %i[date money number percent]
|
28
29
|
|
29
30
|
@filters = {
|
30
|
-
|
31
|
-
|
31
|
+
date: Normalizy::Filters::Date,
|
32
|
+
money: Normalizy::Filters::Money,
|
33
|
+
number: Normalizy::Filters::Number,
|
34
|
+
percent: Normalizy::Filters::Percent,
|
35
|
+
strip: Normalizy::Filters::Strip
|
32
36
|
}
|
33
37
|
end
|
34
38
|
end
|
data/lib/normalizy/extensions.rb
CHANGED
@@ -51,17 +51,21 @@ module Normalizy
|
|
51
51
|
value = nil
|
52
52
|
|
53
53
|
[rules].flatten.compact.each do |rule|
|
54
|
-
|
55
|
-
aliased_rules = [aliases.key?(rule) ? aliases[rule] : rule]
|
54
|
+
result_rules = [aliases.key?(rule) ? aliases[rule] : rule]
|
56
55
|
|
57
|
-
|
58
|
-
filter, filter_options = extract_filter(
|
59
|
-
|
56
|
+
result_rules.flatten.compact.each do |result_rule|
|
57
|
+
filter, filter_options = extract_filter(result_rule)
|
58
|
+
|
59
|
+
if filter.respond_to?(:name)
|
60
|
+
rule_name = filter.name.tableize.split('/').last.singularize.to_sym
|
61
|
+
end
|
62
|
+
|
63
|
+
original = original_value(attribute, rule_name, options)
|
64
|
+
full_options = filter_options.merge(attribute: attribute, object: self)
|
65
|
+
value = extract_value(original, filter, full_options, block)
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
63
|
-
return unless value
|
64
|
-
|
65
69
|
write attribute, value
|
66
70
|
end
|
67
71
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Normalizy
|
4
|
+
module Filters
|
5
|
+
module Date
|
6
|
+
class << self
|
7
|
+
def call(input, options = {})
|
8
|
+
if input.is_a?(String)
|
9
|
+
return input if input.blank?
|
10
|
+
|
11
|
+
Time.use_zone(time_zone(options)) do
|
12
|
+
input = Time.zone.strptime(input, format(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if input.is_a?(Time) || input.is_a?(DateTime)
|
17
|
+
input = input.beginning_of_day if options[:adjust] == :begin
|
18
|
+
input = input.end_of_day if options[:adjust] == :end
|
19
|
+
end
|
20
|
+
|
21
|
+
input
|
22
|
+
rescue ArgumentError
|
23
|
+
options[:object].errors.add options[:attribute], error_message(input, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def error_message(input, options)
|
29
|
+
I18n.t options[:attribute], scope: [
|
30
|
+
'normalizy.errors.date', options[:object].class.name.underscore
|
31
|
+
], value: input, default: '%{value} is an invalid date.'
|
32
|
+
end
|
33
|
+
|
34
|
+
def format(options)
|
35
|
+
options.fetch :format, '%F'
|
36
|
+
end
|
37
|
+
|
38
|
+
def time_zone(options)
|
39
|
+
options.fetch :time_zone, 'UTC'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Normalizy
|
4
|
+
module Filters
|
5
|
+
module Money
|
6
|
+
class << self
|
7
|
+
def call(input, options = {})
|
8
|
+
return input unless input.is_a?(String)
|
9
|
+
|
10
|
+
value = input.gsub(/[^[0-9]#{separator(options)}]/, '')
|
11
|
+
|
12
|
+
return nil if value.blank?
|
13
|
+
|
14
|
+
value = "%0.#{precision(options)}f" % [value.sub(separator(options), '.')]
|
15
|
+
value = value.delete('.') if cents?(options)
|
16
|
+
|
17
|
+
return value.send(options[:cast]) if options[:cast]
|
18
|
+
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def cents?(options)
|
25
|
+
options[:type]&.to_sym == :cents
|
26
|
+
end
|
27
|
+
|
28
|
+
def precision(options)
|
29
|
+
options.fetch :precision, I18n.t('currency.format.precision', default: 2)
|
30
|
+
end
|
31
|
+
|
32
|
+
def separator(options)
|
33
|
+
options.fetch :separator, I18n.t('currency.format.separator', default: '.')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|