decanter 2.1.2 → 3.0.0

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