request_handler 1.1.0 → 2.1.1

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +75 -0
  3. data/CHANGELOG.md +35 -0
  4. data/CODE_OF_CONDUCT.md +69 -0
  5. data/Gemfile +3 -0
  6. data/{LICENSE.txt → LICENSE} +0 -0
  7. data/README.md +241 -45
  8. data/lib/request_handler.rb +8 -16
  9. data/lib/request_handler/base.rb +44 -35
  10. data/lib/request_handler/base_parser.rb +9 -0
  11. data/lib/request_handler/builder/base.rb +23 -0
  12. data/lib/request_handler/builder/body_builder.rb +27 -0
  13. data/lib/request_handler/builder/fieldsets_builder.rb +28 -0
  14. data/lib/request_handler/builder/fieldsets_resource_builder.rb +17 -0
  15. data/lib/request_handler/builder/filter_builder.rb +31 -0
  16. data/lib/request_handler/builder/headers_builder.rb +23 -0
  17. data/lib/request_handler/builder/include_options_builder.rb +23 -0
  18. data/lib/request_handler/builder/multipart_builder.rb +22 -0
  19. data/lib/request_handler/builder/multipart_resource_builder.rb +35 -0
  20. data/lib/request_handler/builder/options_builder.rb +97 -0
  21. data/lib/request_handler/builder/page_builder.rb +30 -0
  22. data/lib/request_handler/builder/page_resource_builder.rb +23 -0
  23. data/lib/request_handler/builder/query_builder.rb +23 -0
  24. data/lib/request_handler/builder/sort_options_builder.rb +23 -0
  25. data/lib/request_handler/concerns/config_helper.rb +25 -0
  26. data/lib/request_handler/config.rb +33 -0
  27. data/lib/request_handler/error.rb +14 -3
  28. data/lib/request_handler/fieldsets_parser.rb +35 -11
  29. data/lib/request_handler/filter_parser.rb +25 -1
  30. data/lib/request_handler/header_parser.rb +30 -3
  31. data/lib/request_handler/include_option_parser.rb +19 -6
  32. data/lib/request_handler/json_api_document_parser.rb +15 -1
  33. data/lib/request_handler/multipart_parser.rb +25 -17
  34. data/lib/request_handler/option_parser.rb +3 -3
  35. data/lib/request_handler/page_parser.rb +33 -17
  36. data/lib/request_handler/query_parser.rb +8 -0
  37. data/lib/request_handler/schema_parser.rb +41 -21
  38. data/lib/request_handler/sort_option_parser.rb +18 -7
  39. data/lib/request_handler/validation/definition_engine.rb +35 -0
  40. data/lib/request_handler/validation/dry_engine.rb +58 -0
  41. data/lib/request_handler/validation/engine.rb +32 -0
  42. data/lib/request_handler/validation/errors.rb +5 -0
  43. data/lib/request_handler/validation/result.rb +17 -0
  44. data/lib/request_handler/version.rb +1 -1
  45. data/request_handler.gemspec +9 -8
  46. metadata +66 -42
  47. data/.travis.yml +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bdc41be4882152511b384885eb59192f5173abb7f08e9f2c32f06030c571821
4
- data.tar.gz: 910f9f1a2a227c1536c3153857eca1906313a6594d6e66c13989fdb78ef6af39
3
+ metadata.gz: f859646a0aa398cdae621ee5fa65dfc141041f2d7459130e43c6dd187f33cd34
4
+ data.tar.gz: 58ac3fcdfdace2cef4810ff885cf9f43b98902c37a84aea56489359df14741ed
5
5
  SHA512:
6
- metadata.gz: c0ee7d6b5160d2f8e4a5c33501aecc4cbd43c6c8d1cbb7dd54a6ecd3700ddedf7f600dffc3b6985775b3f7fae4d077a88774b3f6d3762c7a1f79e386162e190d
7
- data.tar.gz: b912e9cde9288dee5e004c1ad71e9f0a9e985e7bc5ff4fe742b1284078ab7c35d882a757b3ae4235b3d5968fc12f29c1c3c6d37ee106960661134e3a36441042
6
+ metadata.gz: 246011e015199ccabf514606819ee30ff53784e658f756fb891c3dba75b8af20a962910c4251401a9b770f194c06a089c15f2f10e1eadd78061128bba8c49872
7
+ data.tar.gz: ab07fa30b9095bcc7dbc41cd5fe948e80fa84d55252fb9b02b6a8ea656324f4c597d7e469b6d70b976b66a08f013f66feb71fbe141208deb71bc82a491292502
@@ -0,0 +1,75 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+
6
+ common_steps: &common_steps
7
+ - checkout
8
+ - run: gem update --system
9
+ - restore_cache:
10
+ key: gem-cache-{{ .Branch }}-{{ checksum "request_handler.gemspec" }}
11
+ - run:
12
+ name: install dependencies
13
+ command: |
14
+ gem update bundler
15
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
16
+ - save_cache:
17
+ key: gem-cache-{{ .Branch }}-{{ checksum "request_handler.gemspec" }}
18
+ paths:
19
+ - vendor/bundle
20
+
21
+ - run: ruby -v
22
+ - run: bundle exec danger
23
+ - run:
24
+ name: run tests
25
+ command: |
26
+ mkdir /tmp/test-results
27
+ TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
28
+ circleci tests split --split-by=timings)"
29
+
30
+ bundle exec rspec \
31
+ --format progress \
32
+ --format RspecJunitFormatter \
33
+ --out /tmp/test-results/rspec.xml \
34
+ --format progress \
35
+ $TEST_FILES
36
+ # collect reports
37
+ - store_test_results:
38
+ path: /tmp/test-results
39
+ - store_artifacts:
40
+ path: /tmp/test-results
41
+ destination: test-results
42
+
43
+ version: 2
44
+ jobs:
45
+ ruby-2.4:
46
+ docker:
47
+ - image: circleci/ruby:2.4
48
+ steps:
49
+ *common_steps
50
+ ruby-2.5:
51
+ docker:
52
+ - image: circleci/ruby:2.5
53
+ steps:
54
+ *common_steps
55
+ jruby-9.2:
56
+ docker:
57
+ - image: circleci/jruby:9.2
58
+ steps:
59
+ *common_steps
60
+ jruby-9.2-indy:
61
+ docker:
62
+ - image: circleci/jruby:9.2
63
+ environment:
64
+ JRUBY_OPTS: '-Xcompile.invokedynamic=true'
65
+ steps:
66
+ *common_steps
67
+
68
+ workflows:
69
+ version: 2
70
+ build:
71
+ jobs:
72
+ - ruby-2.4
73
+ - ruby-2.5
74
+ - jruby-9.2
75
+ - jruby-9.2-indy
data/CHANGELOG.md CHANGED
@@ -6,6 +6,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.1.1] - 2021-06-14
10
+ ### Fixed
11
+ - Change error object's source attribute from `param` to `parameters` to align with JSONAPI specification
12
+
13
+ ## [2.1.0] - 2020-04-01
14
+ ### Added
15
+ - Headers validation
16
+
17
+ ## [2.0.0] - 2019-11-19
18
+ ### Changed
19
+ - BREAKING: Required configuration of validation engine
20
+ - BREAKING: Dynamic resource keys in config DSL are not supported anymore and
21
+ have to be defined via the `resource` key
22
+
23
+ ### Added
24
+ - Support for dry-* 1.x
25
+
26
+ ### Removed
27
+ - BREAKING: Dry dependencies were removed and should manually be added
28
+ - BREAKING: Support for config inheritance
29
+ - BREAKING: Support for dry-* 0.x
30
+
31
+ ## [1.3.0] - 2019-05-21
32
+ ### Added
33
+ - Serializable JSONAPI error objects out of validation failures
34
+ - Configuration option to enable returning validation failures in errors method of exceptions
35
+
36
+ ### Changed
37
+ - Format of error messages for external causes (bad requests)
38
+ - Inheritance chain of error classes
39
+
40
+ ## [1.2.0] - 2019-04-15
41
+ ### Added
42
+ - Apart from dry-validation, now definition or any other validation library can be used
43
+
9
44
  ## [1.1.0] - 2018-07-13
10
45
  ### Changed
11
46
  - loosen dry-gems restrictions, now allow all version > 0.11
@@ -0,0 +1,69 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, sex characteristics, gender identity and expression,
9
+ level of experience, education, socio-economic status, nationality, personal
10
+ appearance, race, religion, or sexual identity and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Project maintainers who do not follow or enforce the Code of Conduct in good
58
+ faith may face temporary or permanent repercussions as determined by other
59
+ members of the project's leadership.
60
+
61
+ ## Attribution
62
+
63
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
64
+ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
65
+
66
+ [homepage]: https://www.contributor-covenant.org
67
+
68
+ For answers to common questions about this code of conduct, see
69
+ https://www.contributor-covenant.org/faq
data/Gemfile CHANGED
@@ -9,4 +9,7 @@ group :development, :test do
9
9
  gem 'danger'
10
10
  gem 'danger-commit_lint'
11
11
  gem 'danger-rubocop'
12
+ gem 'dry-types', '~> 1.0'
13
+ gem 'dry-validation', '~> 1.0'
14
+ gem 'rspec_junit_formatter'
12
15
  end
File without changes
data/README.md CHANGED
@@ -1,19 +1,13 @@
1
1
  # RequestHandler
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/request_handler.svg)](https://badge.fury.io/rb/request_handler)
4
- [![Build Status](https://travis-ci.org/runtastic/request_handler.svg?branch=master)](https://travis-ci.org/runtastic/request_handler)
4
+ [![CircleCI](https://circleci.com/gh/andreaseger/receptacle.svg?style=svg)](https://circleci.com/gh/runtastic/request_handler)
5
5
  [![codecov](https://codecov.io/gh/runtastic/request_handler/branch/master/graph/badge.svg)](https://codecov.io/gh/runtastic/request_handler)
6
6
 
7
7
  This gem allows easy and dry handling of requests based on the dry-validation
8
8
  gem for validation and data coersion. It allows to handle headers, filters,
9
9
  include_options, sorting and of course to validate the body.
10
10
 
11
- ## dry-gem dependency
12
-
13
- Version 1.1 removes the strict dependency to dry-types v0.11 & dry-validation v0.11 and allows usage of newer versions of dry-gems. This gem uses these gems but only a very small interface with them therefore this gem itself is usually not impacted by smaller breaking changes each minor version of the dry-gems might introduce.
14
-
15
- **Please check your applications compatibility with each dry-types version and pin versions as necessary**
16
-
17
11
  ## Installation
18
12
 
19
13
  Add this line to your application's Gemfile:
@@ -30,12 +24,65 @@ Or install it yourself as:
30
24
 
31
25
  $ gem install request_handler
32
26
 
27
+ ## Configuration
28
+
29
+ You have to chose a validation engine and configure it globally:
30
+ ```ruby
31
+ RequestHandler.configure do |config|
32
+ config.validation_engine = RequestHandler::Validation::DryEngine
33
+ end
34
+ ```
35
+
36
+ If you want to use the included dry engine you also have to add the dry gems to
37
+ your Gemfile:
38
+ ```ruby
39
+ gem 'dry-validation', '~> 1.0'
40
+ gem 'dry-types', '~> 1.0'
41
+ ```
42
+ Note that only dry >= 1.0 is supported.
43
+
44
+ The default logger and separator can be changed globally:
45
+
46
+ ```ruby
47
+ RequestHandler.configure do |config|
48
+ config.logger = Logger.new(STDERR)
49
+ config.separator = '____'
50
+ end
51
+ ```
52
+
53
+ JSON:API-style error data can be included in validation errors raised by `RequestHandler`.
54
+
55
+ ```ruby
56
+ RequestHandler.configure do |config|
57
+ config.raise_jsonapi_errors = true # default: false
58
+ end
59
+ ```
60
+
61
+
62
+ ### Validation Engine
63
+ You have to chose a validation engine and configure it globally (see
64
+ configuration section above).
65
+ All examples in this Readme assume you are using the `DryEngine` which relies on
66
+ dry-validation. However you can also use the builtin `DefinitionEngine`, which
67
+ uses [Definition](https://github.com/Goltergaul/definition) as validation
68
+ library:
69
+
70
+ ```ruby
71
+ RequestHandler.configure do |config|
72
+ require 'request_handler/validation/definition_engine'
73
+ config.validation_engine = RequestHandler::Validation::DefinitionEngine
74
+ end
75
+ ```
76
+
77
+ You can also implement your own engine to use any other library, by implementing
78
+ the abstract class `RequestHandler::Validation::Engine`
79
+
33
80
  ## Usage
34
81
 
35
82
  To set up a handler, you need create a class which inherits from
36
83
  `RequestHandler::Base`, providing at least the options block and a `to_dto`
37
84
  method with the parts you want to use. To use it, create a new instance of the
38
- handler passing in the request, after that you can use the handler.dto method to
85
+ handler passing in the request, after that you can use the handler.to_dto method to
39
86
  process and access the data. Here is a short example, check
40
87
  `spec/integration/request_handler_spec.rb` for a detailed one.
41
88
 
@@ -55,14 +102,13 @@ defines if the JsonApiDocumentParser or JsonParser is used.
55
102
  If nothing is defined, JsonApiDocumentParser will be used by default.
56
103
 
57
104
  ```ruby
58
- require "dry-validation"
59
105
  require "request_handler"
60
106
  class DemoHandler < RequestHandler::Base
61
107
  options do
62
108
  page do
63
109
  default_size 10
64
110
  max_size 20
65
- comments do
111
+ resource :comments do
66
112
  default_size 20
67
113
  max_size 100
68
114
  end
@@ -78,11 +124,11 @@ class DemoHandler < RequestHandler::Base
78
124
 
79
125
  filter do
80
126
  schema(
81
- Dry::Validation.Params do
82
- configure do
83
- option :foo
127
+ Class.new(Dry::Validation::Contract) do
128
+ option :foo
129
+ params do
130
+ required(:name).filled(:string)
84
131
  end
85
- required(:name).filled(:str?)
86
132
  end
87
133
  )
88
134
  additional_url_filter %i(user_id id)
@@ -92,8 +138,8 @@ class DemoHandler < RequestHandler::Base
92
138
 
93
139
  query do
94
140
  schema(
95
- Dry::Validation.Params do
96
- optional(:name).filled(:str?)
141
+ Dry::Schema.Params do
142
+ optional(:name).filled(:string)
97
143
  end
98
144
  )
99
145
  end
@@ -101,11 +147,11 @@ class DemoHandler < RequestHandler::Base
101
147
  body do
102
148
  type :jsonapi
103
149
  schema(
104
- Dry::Validation.JSON do
105
- configure do
106
- option :foo
150
+ Class.new(Dry::Validation::Contract) do
151
+ option :foo
152
+ json do
153
+ required(:id).filled(:string)
107
154
  end
108
- required(:id).filled(:str?)
109
155
  end
110
156
  )
111
157
  options(->(_handler, _request) { { foo: "bar" } })
@@ -178,19 +224,19 @@ file related to the question
178
224
  class CreateQuestionHandler < RequestHandler::Base
179
225
  options do
180
226
  multipart do
181
- question do
227
+ resource :question do
182
228
  required true
183
229
  type "json"
184
230
  schema(
185
- Dry::Validation.JSON do
186
- required(:id).filled(:str?)
187
- required(:type).filled(:str?)
188
- required(:content).filled(:str?)
231
+ Dry::Schema.JSON do
232
+ required(:id).filled(:string)
233
+ required(:type).filled(:string)
234
+ required(:content).filled(:string)
189
235
  end
190
236
  )
191
237
  end
192
238
 
193
- file do
239
+ resource :file do
194
240
  # no validation necessary
195
241
  end
196
242
  end
@@ -203,7 +249,7 @@ class CreateQuestionHandler < RequestHandler::Base
203
249
  end
204
250
  ```
205
251
 
206
- Assuming that the request consists of a json file `question.json` containing
252
+ Assuming that the request consists of a json file `question.json` containing
207
253
  ``` json
208
254
  {
209
255
  "id": "1",
@@ -235,18 +281,44 @@ and an additional file `image.png`, the resulting `multipart_params` will be the
235
281
 
236
282
  Please note that each part's content has to be uploaded as a separate file currently.
237
283
 
238
- ### Configuration
284
+ ### JSON:API errors
285
+
286
+ Errors caused by bad requests respond to `:errors`.
287
+
288
+ When the gem is configured to `raise_jsonapi_errors`, this method returns a list of hashes
289
+ containing `code`, `status`, `detail`, (`links`) and `source` for each specific issue
290
+ that contributed to the error. Otherwise it returns an empty array.
239
291
 
240
- The default logger and separator can be changed globally by using
241
- `RequestHandler.configure {}`.
292
+ The exception message contains `<error code>: <source> <detail>` for every issue,
293
+ with one issue per line.
242
294
 
295
+ | `:code` | `:status` | What is it? |
296
+ |:--------------------------|:----------|:------------|
297
+ | INVALID_RESOURCE_SCHEMA | 422 | Resource did not pass configured validation |
298
+ | INVALID_QUERY_PARAMETER | 400 | Query parameter violates syntax or did not pass configured validation |
299
+ | MISSING_QUERY_PARAMETER | 400 | Query parameter required in configuration is missing |
300
+ | INVALID_JSON_API | 400 | Request body violates JSON:API syntax |
301
+ | INVALID_MULTIPART_REQUEST | 400 | Sidecar resource missing or invalid JSON |
302
+
303
+ #### Example
243
304
  ```ruby
244
- RequestHandler.configure do
245
- logger Logger.new(STDERR)
246
- separator '____'
305
+ rescue RequestHandler::SchemaValidationError => e
306
+ puts e.errors
247
307
  end
248
308
  ```
249
309
 
310
+ ```ruby
311
+ [
312
+ {
313
+ status: '422',
314
+ code: 'INVALID_RESOURCE_SCHEMA',
315
+ title: 'Invalid resource',
316
+ detail: 'is missing',
317
+ source: { pointer: '/data/attributes/name' }
318
+ }
319
+ ]
320
+ ```
321
+
250
322
  ### Caveats
251
323
 
252
324
  It is currently expected that _url_ parameter are already parsed and included in
@@ -261,25 +333,149 @@ get "/users/:user_id/posts" do
261
333
  end
262
334
  ```
263
335
 
336
+ ## v1 to v2 migration guide
337
+ Multiple breaking changes were introduced with request_handler 2.0. This section
338
+ describes which steps have to be taken in order to migrate from 1.x to 2.0.
339
+
340
+ ### Configure validation engine
341
+ By default the DryEngine was used in 1.0. You now have to explicitly configure
342
+ a validation engine:
343
+
344
+ ```ruby
345
+ RequestHandler.configure do |config|
346
+ config.validation_engine = RequestHandler::Validation::DryEngine
347
+ end
348
+ ```
349
+
350
+ ### Add dry dependency if you use the DryEngine
351
+ Since the DryEngine is not configured by default anymore, the dependency to the
352
+ dry gems could be removed from request_handler. If you use the DryEngine
353
+ simply add the dry-gems to your Gemfile:
354
+
355
+ ```ruby
356
+ gem 'dry-validation', '~> 1.0'
357
+ gem 'dry-types', '~> 1.0'
358
+ ```
359
+ Note that only dry >= 1.0 is supported.
360
+
361
+ ### Define custom resources via the `resource` key
362
+ In request_handler 1.x it was possible to define custom resource names like this:
363
+
364
+ ```ruby
365
+ options do
366
+ fieldsets do
367
+ allowed do
368
+ posts schema
369
+ end
370
+ end
371
+ end
372
+ ```
373
+
374
+ This was possible in multiple places (`page`, `multipart`, `fieldsets.allowed`).
375
+ Starting with version 2.0 you will have to define those custom resources via the
376
+ `resource` key:
377
+
378
+ ```ruby
379
+ options do
380
+ fieldsets do
381
+ allowed do
382
+ resource :posts, schema
383
+ end
384
+ end
385
+ end
386
+ ```
387
+
388
+ ### Use dry-* 1.x instead of dry-* 0.x if you use the DryEngine
389
+ Some of the most common required changes are listed here:
390
+
391
+ * Use `Dry::Schema.Params` instead of `Dry::Validation.Schema`
392
+ * Use `Dry::Schema.JSON` instead of `Dry::Validation.JSON`
393
+ * If you use some more complex validation rules with options like this:
394
+
395
+ ```
396
+ Dry::Validation.Params do
397
+ configure do
398
+ option :query_id
399
+ end
400
+ required(:id).value(eql?: query_id)
401
+ end
402
+
403
+ options(->(_parser, request) { { query_id: request.params['id'] } })
404
+ ```
405
+
406
+ please rewrite it using `Dry::Validation::Contract` like this:
407
+
408
+ ```
409
+ Class.new(Dry::Validation::Contract) do
410
+ option :query_id
411
+ params do
412
+ required(:id).value(:string)
413
+ end
414
+ rule(:id) do
415
+ key.failure('invalid id') unless values[:id] == query_id
416
+ end
417
+ end)
418
+ options(->(_parser, request) { { query_id: request.params['id'] } })
419
+ ```
420
+
421
+ A useful guide for upgrading to dry 1 types, validations and schemas can be
422
+ found [here](https://www.morozov.is/2019/05/31/upgrading-dry-gems.html).
423
+
424
+ Also please refer to the official docs of
425
+ [dry-schema](https://dry-rb.org/gems/dry-schema) and
426
+ [dry-validation](https://dry-rb.org/gems/dry-validation).
427
+
428
+ ### Remove config inheritance
429
+ It was possible to (partially) overwrite configs defined in a request-handler
430
+ super-class:
431
+ ```
432
+ class Parent < RequestHandler::Base
433
+ options do
434
+ page do
435
+ comments do
436
+ default_size 20
437
+ end
438
+ end
439
+ end
440
+ end
441
+ ```
442
+
443
+ ```ruby
444
+ class Child < Parent
445
+ options do
446
+ page do
447
+ comments do
448
+ default_size 10
449
+ end
450
+ end
451
+ end
452
+ end
453
+ ```
454
+
455
+ Support for this has been fully removed. If you overwrite configs in subclasses
456
+ please remove the inheritance and define the two request-handlers separately.
457
+
264
458
  ## Development
265
459
 
266
- After checking out the repo, run `bin/setup` to install dependencies. Then, run
267
- `rake test` to run the tests. You can also run `bin/console` for an interactive
268
- prompt that will allow you to experiment.
460
+ After checking out the repo, run `bin/setup` to install dependencies. You can
461
+ also run `bin/console` for an interactive prompt that will allow you to experiment.
462
+
463
+ Run `bundle exec rspec` to run the tests.
269
464
 
270
465
  To install this gem onto your local machine, run `bundle exec rake install`. To
271
466
  release a new version, update the version number in `version.rb`, and then run
272
- `bundle exec rake release`, which will create a git tag for the version, push
273
- git commits and tags, and push the `.gem` file
274
- to [rubygems.org](https://rubygems.org).
467
+ `bundle exec rake release`, which will create a git tag for the version, push git
468
+ commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
275
469
 
276
470
  ## Contributing
277
- Bug reports and pull requests are welcome on GitHub at
278
- https://github.com/runtastic/request_handler. This project is intended to be a
279
- safe, welcoming space for collaboration, and contributors are expected to adhere
280
- to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
471
+ Bug reports and pull requests are welcome on GitHub at https://github.com/runtastic/request_handler.
472
+ This project is intended to be a safe, welcoming space for collaboration, and
473
+ contributors are expected to adhere to the [code of conduct][cc].
474
+
475
+ Check out our [career page](https://www.runtastic.com/career/) if you'd like to work with us.
281
476
 
282
477
  ## License
478
+ The gem is available as open source under [the terms of the MIT License][mit].
283
479
 
284
- The gem is available as open source under the terms of
285
- the [MIT License](http://opensource.org/licenses/MIT).
480
+ [mit]: https://choosealicense.com/licenses/mit/
481
+ [cc]: ../CODE_OF_CONDUCT.md