decanter 2.1.2 → 3.0.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/.codeclimate.yml +38 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +102 -0
- data/LICENSE.txt +21 -0
- data/README.md +232 -0
- data/Rakefile +1 -0
- data/bin/console +3 -4
- data/decanter.gemspec +39 -0
- data/lib/decanter.rb +18 -10
- data/lib/decanter/base.rb +0 -2
- data/lib/decanter/configuration.rb +2 -3
- data/lib/decanter/core.rb +136 -126
- data/lib/decanter/exceptions.rb +4 -7
- data/lib/decanter/extensions.rb +11 -11
- data/lib/decanter/parser.rb +13 -5
- data/lib/decanter/parser/array_parser.rb +29 -0
- data/lib/decanter/parser/base.rb +1 -2
- data/lib/decanter/parser/boolean_parser.rb +4 -3
- data/lib/decanter/parser/compose_parser.rb +27 -0
- data/lib/decanter/parser/core.rb +8 -16
- data/lib/decanter/parser/date_parser.rb +6 -7
- data/lib/decanter/parser/datetime_parser.rb +15 -0
- data/lib/decanter/parser/float_parser.rb +7 -5
- data/lib/decanter/parser/hash_parser.rb +6 -9
- data/lib/decanter/parser/integer_parser.rb +8 -4
- data/lib/decanter/parser/pass_parser.rb +5 -3
- data/lib/decanter/parser/phone_parser.rb +3 -3
- data/lib/decanter/parser/string_parser.rb +4 -5
- data/lib/decanter/parser/utils.rb +1 -3
- data/lib/decanter/parser/value_parser.rb +3 -4
- data/lib/decanter/railtie.rb +15 -11
- data/lib/decanter/version.rb +1 -3
- data/lib/generators/decanter/install_generator.rb +3 -5
- data/lib/generators/decanter/templates/initializer.rb +1 -4
- data/lib/generators/rails/decanter_generator.rb +5 -7
- data/lib/generators/rails/parser_generator.rb +3 -5
- data/lib/generators/rails/resource_override.rb +0 -2
- data/migration-guides/v3.0.0.md +21 -0
- metadata +43 -23
- data/lib/decanter/decant.rb +0 -11
- data/lib/decanter/parser/date_time_parser.rb +0 -21
- data/lib/decanter/parser/join_parser.rb +0 -14
- data/lib/decanter/parser/key_value_splitter_parser.rb +0 -18
- data/lib/decanter/parser/time_parser.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba861d2437b9eb12f96d0ec704fd942bdc9d1883759b3e30b17b223e936c1c3e
|
4
|
+
data.tar.gz: f475da814ab3af68c80452de399a4f633403b9ff1fb5756087f9f0eac04b7679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cce2d74bc1e8437510b4a10c586f1cfd67d914d63cd9571c88d3290f1fc08d0050e5950c16ced0b9696548c39b93bc0c20329c2633bd60196b48b8acca9f1c2f
|
7
|
+
data.tar.gz: 90a256b4b3a30e18017b7b4cf471b72425446319dd2ca0a516d9ecb475e014f7717dc7071ba5898d24c9720d562991e228edbbc0e15eb5757d4443d3687d3b37
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
engines:
|
2
|
+
rubocop:
|
3
|
+
enabled: true
|
4
|
+
checks:
|
5
|
+
Rubocop/Style/Documentation:
|
6
|
+
enabled: false
|
7
|
+
Rubocop/Metrics/LineLength:
|
8
|
+
enabled: false
|
9
|
+
Rubocop/Rails/Validation:
|
10
|
+
enabled: false
|
11
|
+
Rubocop/Style/IndentationConsistency:
|
12
|
+
enabled: false
|
13
|
+
Rubocop/Style/EmptyLines:
|
14
|
+
enabled: false
|
15
|
+
Rubocop/Style/ClassAndModuleChildren:
|
16
|
+
enabled: false
|
17
|
+
Rubocop/Style/AccessorMethodName:
|
18
|
+
enabled: false
|
19
|
+
golint:
|
20
|
+
enabled: true
|
21
|
+
gofmt:
|
22
|
+
enabled: true
|
23
|
+
eslint:
|
24
|
+
enabled: true
|
25
|
+
csslint:
|
26
|
+
enabled: true
|
27
|
+
brakeman:
|
28
|
+
enabled: false
|
29
|
+
bundler-audit:
|
30
|
+
enabled: true
|
31
|
+
ratings:
|
32
|
+
paths:
|
33
|
+
- lib/**
|
34
|
+
- "**.rb"
|
35
|
+
exclude_paths:
|
36
|
+
- bin/**/*
|
37
|
+
- spec/**/*
|
38
|
+
- coverage/**/*
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.5
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
decanter (3.0.0)
|
5
|
+
actionpack (>= 4.2.10)
|
6
|
+
activesupport
|
7
|
+
rails-html-sanitizer (>= 1.0.4)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actionpack (5.1.4)
|
13
|
+
actionview (= 5.1.4)
|
14
|
+
activesupport (= 5.1.4)
|
15
|
+
rack (~> 2.0)
|
16
|
+
rack-test (>= 0.6.3)
|
17
|
+
rails-dom-testing (~> 2.0)
|
18
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
19
|
+
actionview (5.1.4)
|
20
|
+
activesupport (= 5.1.4)
|
21
|
+
builder (~> 3.1)
|
22
|
+
erubi (~> 1.4)
|
23
|
+
rails-dom-testing (~> 2.0)
|
24
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
25
|
+
activesupport (5.1.4)
|
26
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
27
|
+
i18n (~> 0.7)
|
28
|
+
minitest (~> 5.1)
|
29
|
+
tzinfo (~> 1.1)
|
30
|
+
builder (3.2.3)
|
31
|
+
concurrent-ruby (1.0.5)
|
32
|
+
crass (1.0.4)
|
33
|
+
diff-lcs (1.3)
|
34
|
+
docile (1.1.5)
|
35
|
+
dotenv (2.2.1)
|
36
|
+
erubi (1.7.0)
|
37
|
+
i18n (0.9.3)
|
38
|
+
concurrent-ruby (~> 1.0)
|
39
|
+
json (2.1.0)
|
40
|
+
loofah (2.2.2)
|
41
|
+
crass (~> 1.0.2)
|
42
|
+
nokogiri (>= 1.5.9)
|
43
|
+
method_source (0.9.0)
|
44
|
+
mini_portile2 (2.3.0)
|
45
|
+
minitest (5.11.3)
|
46
|
+
nokogiri (1.8.5)
|
47
|
+
mini_portile2 (~> 2.3.0)
|
48
|
+
rack (2.0.4)
|
49
|
+
rack-test (0.8.2)
|
50
|
+
rack (>= 1.0, < 3)
|
51
|
+
rails-dom-testing (2.0.3)
|
52
|
+
activesupport (>= 4.2.0)
|
53
|
+
nokogiri (>= 1.6)
|
54
|
+
rails-html-sanitizer (1.0.4)
|
55
|
+
loofah (~> 2.2, >= 2.2.2)
|
56
|
+
railties (5.1.4)
|
57
|
+
actionpack (= 5.1.4)
|
58
|
+
activesupport (= 5.1.4)
|
59
|
+
method_source
|
60
|
+
rake (>= 0.8.7)
|
61
|
+
thor (>= 0.18.1, < 2.0)
|
62
|
+
rake (10.5.0)
|
63
|
+
rspec-core (3.7.1)
|
64
|
+
rspec-support (~> 3.7.0)
|
65
|
+
rspec-expectations (3.7.0)
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
+
rspec-support (~> 3.7.0)
|
68
|
+
rspec-mocks (3.7.0)
|
69
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
70
|
+
rspec-support (~> 3.7.0)
|
71
|
+
rspec-rails (3.7.2)
|
72
|
+
actionpack (>= 3.0)
|
73
|
+
activesupport (>= 3.0)
|
74
|
+
railties (>= 3.0)
|
75
|
+
rspec-core (~> 3.7.0)
|
76
|
+
rspec-expectations (~> 3.7.0)
|
77
|
+
rspec-mocks (~> 3.7.0)
|
78
|
+
rspec-support (~> 3.7.0)
|
79
|
+
rspec-support (3.7.1)
|
80
|
+
simplecov (0.15.1)
|
81
|
+
docile (~> 1.1.0)
|
82
|
+
json (>= 1.8, < 3)
|
83
|
+
simplecov-html (~> 0.10.0)
|
84
|
+
simplecov-html (0.10.2)
|
85
|
+
thor (0.20.0)
|
86
|
+
thread_safe (0.3.6)
|
87
|
+
tzinfo (1.2.5)
|
88
|
+
thread_safe (~> 0.1)
|
89
|
+
|
90
|
+
PLATFORMS
|
91
|
+
ruby
|
92
|
+
|
93
|
+
DEPENDENCIES
|
94
|
+
bundler (~> 1.9)
|
95
|
+
decanter!
|
96
|
+
dotenv
|
97
|
+
rake (~> 10.0)
|
98
|
+
rspec-rails
|
99
|
+
simplecov (~> 0.15.1)
|
100
|
+
|
101
|
+
BUNDLED WITH
|
102
|
+
1.17.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
# Decanter
|
2
|
+
|
3
|
+
Decanter is a Ruby gem that makes it easy to transform incoming data before it hits the model.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
gem 'decanter', '~> 3.0'
|
7
|
+
```
|
8
|
+
|
9
|
+
## Contents
|
10
|
+
|
11
|
+
- [Migration guides](#migration-guides)
|
12
|
+
- [Basic Usage](#basic-usage)
|
13
|
+
- [Decanters](#decanters)
|
14
|
+
- [Generators](#generators)
|
15
|
+
- [Nested resources](#nested-resources)
|
16
|
+
- [Default parsers](#default-parsers)
|
17
|
+
- [Parser options](#parser-options)
|
18
|
+
- [Exceptions](#exceptions)
|
19
|
+
- [Advanced usage](#advanced-usage)
|
20
|
+
- [Custom parsers](#custom-parsers)
|
21
|
+
- [Squashing inputs](#squashing-inputs)
|
22
|
+
- [Chaining parsers](#chaining-parsers)
|
23
|
+
- [Requiring params](#requiring-params)
|
24
|
+
- [Global configuration](#global-configuration)
|
25
|
+
|
26
|
+
## Migration Guides
|
27
|
+
|
28
|
+
- [v3.0.0](migration-guides/v3.0.0.md)
|
29
|
+
|
30
|
+
## Basic Usage
|
31
|
+
|
32
|
+
### Decanters
|
33
|
+
|
34
|
+
Declare a `Decanter` for a model:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# app/decanters/trip_decanter.rb
|
38
|
+
|
39
|
+
class TripDecanter < Decanter::Base
|
40
|
+
input :name, :string
|
41
|
+
input :start_date, :date
|
42
|
+
input :end_date, :date
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Transform incoming params in your controller using `Decanter#decant`:
|
47
|
+
|
48
|
+
```rb
|
49
|
+
# app/controllers/trips_controller.rb
|
50
|
+
|
51
|
+
def create
|
52
|
+
trip_params = TripDecanter.decant(params[:trip])
|
53
|
+
@trip = Trip.new(trip_params)
|
54
|
+
|
55
|
+
# ...any response logic
|
56
|
+
end
|
57
|
+
|
58
|
+
```
|
59
|
+
|
60
|
+
### Generators
|
61
|
+
|
62
|
+
Decanter comes with generators for creating `Decanter` and `Parser` files:
|
63
|
+
|
64
|
+
```
|
65
|
+
rails g decanter Trip name:string start_date:date end_date:date
|
66
|
+
```
|
67
|
+
|
68
|
+
```
|
69
|
+
rails g parser TruncatedString
|
70
|
+
```
|
71
|
+
|
72
|
+
### Nested resources
|
73
|
+
|
74
|
+
Decanters can declare relationships using `ActiveRecord`-style declarators:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
class TripDecanter < Decanter::Base
|
78
|
+
has_many :destinations
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
### Default parsers
|
83
|
+
|
84
|
+
Decanter comes with the following parsers out of the box:
|
85
|
+
|
86
|
+
- `:boolean`
|
87
|
+
- `:date`
|
88
|
+
- `:date_time`
|
89
|
+
- `:float`
|
90
|
+
- `:integer`
|
91
|
+
- `:pass`
|
92
|
+
- `:phone`
|
93
|
+
- `:string`
|
94
|
+
- `:array`
|
95
|
+
|
96
|
+
Note: these parsers are designed to operate on a single value, except for `:array`. This parser expects an array, and will use the `parse_each` option to call a given parser on each of its elements:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
input :ids, :array, parse_each: :integer
|
100
|
+
```
|
101
|
+
|
102
|
+
### Parser options
|
103
|
+
|
104
|
+
Parsers can receive options that modify their behavior. These options are passed in as named arguments to `input`:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
input :start_date, :date, parse_format: '%Y-%m-%d'
|
108
|
+
```
|
109
|
+
|
110
|
+
This decanter will look up and apply the corresponding `DestinationDecanter` whenever necessary to transform nested resources.
|
111
|
+
|
112
|
+
### Exceptions
|
113
|
+
|
114
|
+
By default, `Decanter#decant` will raise an exception when unexpected parameters are passed. To override this behavior, you can disable strict mode:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
class TripDecanter < Decanter::Base
|
118
|
+
strict false
|
119
|
+
# ...
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
Or explicitly ignore a key:
|
124
|
+
|
125
|
+
```rb
|
126
|
+
class TripDecanter < Decanter::Base
|
127
|
+
ignore :created_at, :updated_at
|
128
|
+
# ...
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
You can also disable strict mode globally using a [global configuration](#global-configuration) setting.
|
133
|
+
|
134
|
+
## Advanced Usage
|
135
|
+
|
136
|
+
### Custom Parsers
|
137
|
+
|
138
|
+
To add a custom parser, first create a parser class:
|
139
|
+
|
140
|
+
```rb
|
141
|
+
# app/parsers/truncate_string_parser.rb
|
142
|
+
class TruncateStringParser < Decanter::Parser::ValueParser
|
143
|
+
|
144
|
+
parser do |value, options|
|
145
|
+
length = options.fetch(:length, 100)
|
146
|
+
value.truncate(length)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
Then, use the appropriate key to look up the parser:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
input :name, :truncate_string #=> TruncateStringParser
|
155
|
+
```
|
156
|
+
|
157
|
+
#### Custom parser methods
|
158
|
+
|
159
|
+
- `#parse <block>`: (required) recieves a block for parsing a value. Block parameters are `|value, options|` for `ValueParser` and `|name, value, options|` for `HashParser`.
|
160
|
+
- `#allow [<class>]`: skips parse step if the incoming value `is_a?` instance of class(es).
|
161
|
+
- `#pre [<parser>]`: applies the given parser(s) before parsing the value.
|
162
|
+
|
163
|
+
#### Custom parser base classes
|
164
|
+
|
165
|
+
- `Decanter::Parser::ValueParser`: subclasses are expected to return a single value.
|
166
|
+
- `Decanter::Parser::HashParser`: subclasses are expected to return a hash of keys and values.
|
167
|
+
|
168
|
+
### Squashing inputs
|
169
|
+
|
170
|
+
Sometimes, you may want to take several inputs and combine them into one finished input prior to sending to your model. You can achieve this with a custom parser:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
class TripDecanter < Decanter::Base
|
174
|
+
input [:day, :month, :year], :squash_date, key: :start_date
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
class SquashDateParser < Decanter::Parser::ValueParser
|
180
|
+
parser do |values, options|
|
181
|
+
day, month, year = values.map(&:to_i)
|
182
|
+
Date.new(year, month, day)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
### Chaining parsers
|
188
|
+
|
189
|
+
You can compose multiple parsers by using the `#pre` method:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
class FloatPercentParser < Decanter::Parser::ValueParser
|
193
|
+
|
194
|
+
pre :float
|
195
|
+
|
196
|
+
parser do |val, options|
|
197
|
+
val / 100
|
198
|
+
end
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
Or by declaring multiple parsers for a single input:
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
class SomeDecanter < Decanter::Base
|
206
|
+
input :some_percent, [:float, :percent]
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
210
|
+
### Requiring params
|
211
|
+
|
212
|
+
If you provide the option `:required` for an input in your decanter, an exception will be thrown if the parameter is `nil` or an empty string.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
class TripDecanter < Decanter::Base
|
216
|
+
input :name, :string, required: true
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
_Note: we recommend using [Active Record validations](https://guides.rubyonrails.org/active_record_validations.html) to check for presence of an attribute, rather than using the `required` option. This method is intended for use in non-RESTful routes or cases where Active Record validations are not available._
|
221
|
+
|
222
|
+
### Global configuration
|
223
|
+
|
224
|
+
You can generate a local copy of the default configuration with `rails generate decanter:install`. This will create an initializer where you can do global configuration:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
# ./config/initializers/decanter.rb
|
228
|
+
|
229
|
+
Decanter.config do |config|
|
230
|
+
config.strict = false
|
231
|
+
end
|
232
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "bundler/setup"
|
4
|
+
require "decanter"
|
6
5
|
|
7
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
8
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -11,5 +10,5 @@ require 'decanter'
|
|
11
10
|
# require "pry"
|
12
11
|
# Pry.start
|
13
12
|
|
14
|
-
require
|
13
|
+
require "irb"
|
15
14
|
IRB.start
|