request_handler 1.1.0 → 2.1.1

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