normalizy 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|