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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +38 -0
  3. data/.gitignore +5 -0
  4. data/.rspec +2 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +10 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +102 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +232 -0
  11. data/Rakefile +1 -0
  12. data/bin/console +3 -4
  13. data/decanter.gemspec +39 -0
  14. data/lib/decanter.rb +18 -10
  15. data/lib/decanter/base.rb +0 -2
  16. data/lib/decanter/configuration.rb +2 -3
  17. data/lib/decanter/core.rb +136 -126
  18. data/lib/decanter/exceptions.rb +4 -7
  19. data/lib/decanter/extensions.rb +11 -11
  20. data/lib/decanter/parser.rb +13 -5
  21. data/lib/decanter/parser/array_parser.rb +29 -0
  22. data/lib/decanter/parser/base.rb +1 -2
  23. data/lib/decanter/parser/boolean_parser.rb +4 -3
  24. data/lib/decanter/parser/compose_parser.rb +27 -0
  25. data/lib/decanter/parser/core.rb +8 -16
  26. data/lib/decanter/parser/date_parser.rb +6 -7
  27. data/lib/decanter/parser/datetime_parser.rb +15 -0
  28. data/lib/decanter/parser/float_parser.rb +7 -5
  29. data/lib/decanter/parser/hash_parser.rb +6 -9
  30. data/lib/decanter/parser/integer_parser.rb +8 -4
  31. data/lib/decanter/parser/pass_parser.rb +5 -3
  32. data/lib/decanter/parser/phone_parser.rb +3 -3
  33. data/lib/decanter/parser/string_parser.rb +4 -5
  34. data/lib/decanter/parser/utils.rb +1 -3
  35. data/lib/decanter/parser/value_parser.rb +3 -4
  36. data/lib/decanter/railtie.rb +15 -11
  37. data/lib/decanter/version.rb +1 -3
  38. data/lib/generators/decanter/install_generator.rb +3 -5
  39. data/lib/generators/decanter/templates/initializer.rb +1 -4
  40. data/lib/generators/rails/decanter_generator.rb +5 -7
  41. data/lib/generators/rails/parser_generator.rb +3 -5
  42. data/lib/generators/rails/resource_override.rb +0 -2
  43. data/migration-guides/v3.0.0.md +21 -0
  44. metadata +43 -23
  45. data/lib/decanter/decant.rb +0 -11
  46. data/lib/decanter/parser/date_time_parser.rb +0 -21
  47. data/lib/decanter/parser/join_parser.rb +0 -14
  48. data/lib/decanter/parser/key_value_splitter_parser.rb +0 -18
  49. data/lib/decanter/parser/time_parser.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '06357965a0176a615be643b95e2d874a4220551e1005297e4d00289c030281bf'
4
- data.tar.gz: 5b91739498814cf560122667e35be29d000185940a65731411fae870d49dff11
3
+ metadata.gz: ba861d2437b9eb12f96d0ec704fd942bdc9d1883759b3e30b17b223e936c1c3e
4
+ data.tar.gz: f475da814ab3af68c80452de399a4f633403b9ff1fb5756087f9f0eac04b7679
5
5
  SHA512:
6
- metadata.gz: 74e7ae10f60661f911620590d9785eb6fadd3a7f80229b48911b3b82dfd3143b38781d59915db8e4beb506d5d409b1f8190f014b521c119a7deae0ccb5a17a91
7
- data.tar.gz: ac9b8c3d70b006f98fe13be3711943567f17adfe8776f71b3ae2ca28690769129cf9391886c51d4053d476e8d1c85786a3a6d281ea7d5b79261009d0875dfd46
6
+ metadata.gz: cce2d74bc1e8437510b4a10c586f1cfd67d914d63cd9571c88d3290f1fc08d0050e5950c16ced0b9696548c39b93bc0c20329c2633bd60196b48b8acca9f1c2f
7
+ data.tar.gz: 90a256b4b3a30e18017b7b4cf471b72425446319dd2ca0a516d9ecb475e014f7717dc7071ba5898d24c9720d562991e228edbbc0e15eb5757d4443d3687d3b37
@@ -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/**/*
@@ -0,0 +1,5 @@
1
+ /coverage
2
+ .env
3
+ .DS_Store
4
+ # Builds for push
5
+ decanter-*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1 @@
1
+ 2.6.5
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ cache:
4
+ bundler: true
5
+
6
+ script:
7
+ - bundle exec rspec
8
+
9
+ notifications:
10
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in goaltender.gemspec
4
+ gemspec
@@ -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
@@ -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.
@@ -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
+ ```
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
2
 
4
- require 'bundler/setup'
5
- require 'decanter'
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 'irb'
13
+ require "irb"
15
14
  IRB.start