README.md in request_handler-1.3.0 vs README.md in request_handler-2.0.0

- old
+ new

@@ -24,38 +24,55 @@ $ gem install request_handler ## Configuration +You have to chose a validation engine and configure it globally: +```ruby +RequestHandler.configure do |config| + config.validation_engine = RequestHandler::Validation::DryEngine +end +``` + +If you want to use the included dry engine you also have to add the dry gems to +your Gemfile: +```ruby + gem 'dry-validation', '~> 1.0' + gem 'dry-types', '~> 1.0' +``` +Note that only dry >= 1.0 is supported. + The default logger and separator can be changed globally: ```ruby -RequestHandler.configure do - logger Logger.new(STDERR) - separator '____' - validation_engine RequestHandler::Validation::DryEngine +RequestHandler.configure do |config| + config.logger = Logger.new(STDERR) + config.separator = '____' end ``` JSON:API-style error data can be included in validation errors raised by `RequestHandler`. ```ruby -RequestHandler.configure do - raise_jsonapi_errors = true # default: false +RequestHandler.configure do |config| + config.raise_jsonapi_errors = true # default: false end ``` ### Validation Engine -Per default this gem uses the `DryEngine` which relies on dry-validation. All -examples in this Readme assume you are using this default engine. However -you can also use the builtin `DefinitionEngine`, which uses [Definition](https://github.com/Goltergaul/definition) as validation library: +You have to chose a validation engine and configure it globally (see +configuration section above). +All examples in this Readme assume you are using the `DryEngine` which relies on +dry-validation. However you can also use the builtin `DefinitionEngine`, which +uses [Definition](https://github.com/Goltergaul/definition) as validation +library: ```ruby -RequestHandler.configure do +RequestHandler.configure do |config| require 'request_handler/validation/definition_engine' - validation_engine RequestHandler::Validation::DefinitionEngine + config.validation_engine = RequestHandler::Validation::DefinitionEngine end ``` You can also implement your own engine to use any other library, by implementing the abstract class `RequestHandler::Validation::Engine` @@ -83,18 +100,17 @@ At the moment there are only "jsonapi" and "json" available for `type`. This defines if the JsonApiDocumentParser or JsonParser is used. If nothing is defined, JsonApiDocumentParser will be used by default. ```ruby -require "dry-validation" require "request_handler" class DemoHandler < RequestHandler::Base options do page do default_size 10 max_size 20 - comments do + resource :comments do default_size 20 max_size 100 end end @@ -106,38 +122,38 @@ allowed Dry::Types["strict.string"].enum("age", "name") end filter do schema( - Dry::Validation.Params do - configure do - option :foo + Class.new(Dry::Validation::Contract) do + option :foo + params do + required(:name).filled(:string) end - required(:name).filled(:str?) end ) additional_url_filter %i(user_id id) options(->(_handler, _request) { { foo: "bar" } }) # options({foo: "bar"}) # also works for hash options instead of procs end query do schema( - Dry::Validation.Params do - optional(:name).filled(:str?) + Dry::Schema.Params do + optional(:name).filled(:string) end ) end body do type :jsonapi schema( - Dry::Validation.JSON do - configure do - option :foo + Class.new(Dry::Validation::Contract) do + option :foo + json do + required(:id).filled(:string) end - required(:id).filled(:str?) end ) options(->(_handler, _request) { { foo: "bar" } }) # options({foo: "bar"}) # also works for hash options instead of procs end @@ -206,23 +222,23 @@ ```ruby class CreateQuestionHandler < RequestHandler::Base options do multipart do - question do + resource :question do required true type "json" schema( - Dry::Validation.JSON do - required(:id).filled(:str?) - required(:type).filled(:str?) - required(:content).filled(:str?) + Dry::Schema.JSON do + required(:id).filled(:string) + required(:type).filled(:string) + required(:content).filled(:string) end ) end - file do + resource :file do # no validation necessary end end end @@ -314,9 +330,131 @@ request.params.merge!(params) dto = DemoHandler.new(request: request).to_dto # more code end ``` + +## v1 to v2 migration guide +Multiple breaking changes were introduced with request_handler 2.0. This section +describes which steps have to be taken in order to migrate from 1.x to 2.0. + +### Configure validation engine +By default the DryEngine was used in 1.0. You now have to explicitly configure +a validation engine: + +```ruby +RequestHandler.configure do |config| + config.validation_engine = RequestHandler::Validation::DryEngine +end +``` + +### Add dry dependency if you use the DryEngine +Since the DryEngine is not configured by default anymore, the dependency to the +dry gems could be removed from request_handler. If you use the DryEngine +simply add the dry-gems to your Gemfile: + +```ruby +gem 'dry-validation', '~> 1.0' +gem 'dry-types', '~> 1.0' +``` +Note that only dry >= 1.0 is supported. + +### Define custom resources via the `resource` key +In request_handler 1.x it was possible to define custom resource names like this: + +```ruby +options do + fieldsets do + allowed do + posts schema + end + end +end +``` + +This was possible in multiple places (`page`, `multipart`, `fieldsets.allowed`). +Starting with version 2.0 you will have to define those custom resources via the +`resource` key: + +```ruby +options do + fieldsets do + allowed do + resource :posts, schema + end + end +end +``` + +### Use dry-* 1.x instead of dry-* 0.x if you use the DryEngine +Some of the most common required changes are listed here: + +* Use `Dry::Schema.Params` instead of `Dry::Validation.Schema` +* Use `Dry::Schema.JSON` instead of `Dry::Validation.JSON` +* If you use some more complex validation rules with options like this: + +``` +Dry::Validation.Params do + configure do + option :query_id + end + required(:id).value(eql?: query_id) +end + +options(->(_parser, request) { { query_id: request.params['id'] } }) +``` + +please rewrite it using `Dry::Validation::Contract` like this: + +``` +Class.new(Dry::Validation::Contract) do + option :query_id + params do + required(:id).value(:string) + end + rule(:id) do + key.failure('invalid id') unless values[:id] == query_id + end +end) +options(->(_parser, request) { { query_id: request.params['id'] } }) +``` + +A useful guide for upgrading to dry 1 types, validations and schemas can be +found [here](https://www.morozov.is/2019/05/31/upgrading-dry-gems.html). + +Also please refer to the official docs of +[dry-schema](https://dry-rb.org/gems/dry-schema) and +[dry-validation](https://dry-rb.org/gems/dry-validation). + +### Remove config inheritance +It was possible to (partially) overwrite configs defined in a request-handler +super-class: +``` +class Parent < RequestHandler::Base + options do + page do + comments do + default_size 20 + end + end + end +end +``` + +```ruby +class Child < Parent + options do + page do + comments do + default_size 10 + end + end + end +end +``` + +Support for this has been fully removed. If you overwrite configs in subclasses +please remove the inheritance and define the two request-handlers separately. ## Development After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.