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
@@ -2,26 +2,18 @@
2
2
 
3
3
  require 'request_handler/version'
4
4
  require 'request_handler/base'
5
- require 'confstruct'
6
- require 'dry-validation'
5
+ require 'request_handler/validation/dry_engine'
7
6
  require 'multi_json'
8
7
  require 'logger'
8
+ require 'gem_config'
9
9
 
10
10
  module RequestHandler
11
- class << self
12
- def configure(&block)
13
- configuration.configure(&block)
14
- end
11
+ include GemConfig::Base
15
12
 
16
- def configuration
17
- @configuration ||= ::Confstruct::Configuration.new do
18
- logger Logger.new(STDOUT)
19
- separator '__'
20
- end
21
- end
22
-
23
- def separator
24
- configuration.separator
25
- end
13
+ with_configuration do
14
+ has :validation_engine
15
+ has :logger, default: Logger.new(STDOUT)
16
+ has :separator, classes: [String], default: '__'
17
+ has :raise_jsonapi_errors, default: false
26
18
  end
27
19
  end
@@ -10,22 +10,22 @@ require 'request_handler/multipart_parser'
10
10
  require 'request_handler/fieldsets_parser'
11
11
  require 'request_handler/query_parser'
12
12
  require 'request_handler/helper'
13
- require 'confstruct'
13
+ require 'request_handler/builder/options_builder'
14
+ require 'request_handler/concerns/config_helper'
15
+ require 'request_handler/config'
16
+
14
17
  module RequestHandler
15
18
  class Base
19
+ include RequestHandler::Concerns::ConfigHelper
20
+
16
21
  class << self
17
22
  def options(&block)
18
- @config ||= ::Confstruct::Configuration.new
19
- @config.configure(&block)
20
- end
21
-
22
- def inherited(subclass)
23
- return if @config.nil?
24
- subclass.config = @config.deep_copy
23
+ @config = Config.new(&block)
25
24
  end
26
25
 
27
26
  attr_accessor :config
28
27
  end
28
+
29
29
  def initialize(request:)
30
30
  raise MissingArgumentError, request: 'is missing' if request.nil?
31
31
  @request = request
@@ -38,7 +38,7 @@ module RequestHandler
38
38
  def page_params
39
39
  @page_params ||= PageParser.new(
40
40
  params: params,
41
- page_config: lookup!('page')
41
+ page_config: config.lookup!('page')
42
42
  ).run
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module RequestHandler
51
51
  end
52
52
 
53
53
  def headers
54
- @headers ||= HeaderParser.new(env: request.env).run
54
+ @headers ||= parse_headers
55
55
  end
56
56
 
57
57
  def body_params
@@ -82,9 +82,9 @@ module RequestHandler
82
82
  defaults = fetch_defaults('filter.defaults', {})
83
83
  defaults.merge(FilterParser.new(
84
84
  params: params,
85
- schema: lookup!('filter.schema'),
86
- additional_url_filter: lookup('filter.additional_url_filter'),
87
- schema_options: execute_options(lookup('filter.options'))
85
+ schema: config.lookup!('filter.schema'),
86
+ additional_url_filter: config.lookup('filter.additional_url_filter'),
87
+ schema_options: execute_options(config.lookup('filter.options'))
88
88
  ).run)
89
89
  end
90
90
 
@@ -100,43 +100,58 @@ module RequestHandler
100
100
  defaults = fetch_defaults("#{type}.defaults", [])
101
101
  result = parser.new(
102
102
  params: params,
103
- allowed_options_type: lookup!("#{type}.allowed")
103
+ allowed_options_type: config.lookup!("#{type}.allowed")
104
104
  ).run
105
105
  result.empty? ? defaults : result
106
106
  end
107
107
 
108
+ def parse_headers
109
+ HeaderParser.new(header_parser_params).run
110
+ end
111
+
112
+ def header_parser_params
113
+ params = { env: request.env }
114
+
115
+ return params if config.nil?
116
+
117
+ params.merge(
118
+ schema: config.lookup('headers.schema'),
119
+ schema_options: execute_options(config.lookup('headers.options'))
120
+ )
121
+ end
122
+
108
123
  def parse_body_params
109
124
  BodyParser.new(
110
125
  request: request,
111
- schema: lookup!('body.schema'),
112
- schema_options: execute_options(lookup('body.options')),
113
- type: lookup('body.type')
126
+ schema: config.lookup!('body.schema'),
127
+ schema_options: execute_options(config.lookup('body.options')),
128
+ type: config.lookup('body.type')
114
129
  ).run
115
130
  end
116
131
 
117
132
  def parse_multipart_params
118
133
  MultipartsParser.new(
119
134
  request: request,
120
- multipart_config: lookup!('multipart')
135
+ multipart_config: config.lookup!('multipart').to_h
121
136
  ).run
122
137
  end
123
138
 
124
139
  def parse_fieldsets_params
125
140
  FieldsetsParser.new(params: params,
126
- allowed: lookup!('fieldsets.allowed'),
127
- required: lookup('fieldsets.required') || []).run
141
+ allowed: config.lookup!('fieldsets.allowed'),
142
+ required: config.lookup('fieldsets.required') || []).run
128
143
  end
129
144
 
130
145
  def parse_query_params
131
146
  QueryParser.new(
132
147
  params: params,
133
- schema: lookup!('query.schema'),
134
- schema_options: execute_options(lookup('query.options'))
148
+ schema: config.lookup!('query.schema'),
149
+ schema_options: execute_options(config.lookup('query.options'))
135
150
  ).run
136
151
  end
137
152
 
138
153
  def fetch_defaults(key, default)
139
- value = lookup(key)
154
+ value = config.lookup(key)
140
155
  return default if value.nil?
141
156
  return value unless value.respond_to?(:call)
142
157
  value.call(request)
@@ -148,26 +163,20 @@ module RequestHandler
148
163
  options.call(self, request)
149
164
  end
150
165
 
151
- def lookup!(key)
152
- config.lookup!(key).tap do |data|
153
- raise NoConfigAvailableError, key.to_sym => 'is not configured' if data.nil?
154
- end
155
- end
156
-
157
- def lookup(key)
158
- config.lookup!(key)
159
- end
160
-
161
166
  def params
162
167
  raise MissingArgumentError, params: 'is missing' if request.params.nil?
163
- raise ExternalArgumentError, params: 'must be a Hash' unless request.params.is_a?(Hash)
168
+ raise ExternalArgumentError, [] unless request.params.is_a?(Hash)
164
169
  @params ||= Helper.deep_transform_keys_in_object(request.params) do |k|
165
- k.to_s.gsub('.', ::RequestHandler.separator)
170
+ k.to_s.gsub('.', separator)
166
171
  end
167
172
  end
168
173
 
169
174
  def config
170
175
  self.class.instance_variable_get('@config')
171
176
  end
177
+
178
+ def separator
179
+ ::RequestHandler.configuration.separator
180
+ end
172
181
  end
173
182
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/concerns/config_helper'
4
+
5
+ module RequestHandler
6
+ class BaseParser
7
+ include RequestHandler::Concerns::ConfigHelper
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class Base
8
+ attr_accessor :result
9
+
10
+ def initialize
11
+ create_klass_struct
12
+ end
13
+
14
+ def create_klass_struct
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def build
19
+ result
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class BodyBuilder < Base
8
+ Body = Struct.new(:type, :schema, :options)
9
+
10
+ def create_klass_struct
11
+ @result = Body.new
12
+ end
13
+
14
+ def type(value)
15
+ @result.type = value
16
+ end
17
+
18
+ def schema(value)
19
+ @result.schema = value
20
+ end
21
+
22
+ def options(value)
23
+ @result.options = value
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+ require 'request_handler/builder/fieldsets_resource_builder'
5
+
6
+ module RequestHandler
7
+ module Builder
8
+ class FieldsetsBuilder < Base
9
+ Fieldsets = Struct.new(:allowed, :required)
10
+
11
+ def create_klass_struct
12
+ @result = Fieldsets.new
13
+ end
14
+
15
+ def allowed(&block)
16
+ @result.allowed = build_fieldsets_resource(&block)
17
+ end
18
+
19
+ def required(value)
20
+ @result.required = value
21
+ end
22
+
23
+ def build_fieldsets_resource(&block)
24
+ Docile.dsl_eval(FieldsetsResourceBuilder.new, &block).build
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "request_handler/builder/base"
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class FieldsetsResourceBuilder < Base
8
+ def create_klass_struct
9
+ @result = OpenStruct.new
10
+ end
11
+
12
+ def resource(name, value)
13
+ @result[name.to_sym] = value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class FilterBuilder < Base
8
+ Filter = Struct.new(:schema, :additional_url_filter, :options, :defaults)
9
+
10
+ def create_klass_struct
11
+ @result = Filter.new
12
+ end
13
+
14
+ def schema(value)
15
+ @result.schema = value
16
+ end
17
+
18
+ def additional_url_filter(value)
19
+ @result.additional_url_filter = value
20
+ end
21
+
22
+ def options(value)
23
+ @result.options = value
24
+ end
25
+
26
+ def defaults(value)
27
+ @result.defaults = value
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class HeadersBuilder < Base
8
+ Headers = Struct.new(:schema, :options)
9
+
10
+ def create_klass_struct
11
+ @result = Headers.new
12
+ end
13
+
14
+ def schema(value)
15
+ @result.schema = value
16
+ end
17
+
18
+ def options(value)
19
+ @result.options = value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class IncludeOptionsBuilder < Base
8
+ IncludeOptions = Struct.new(:allowed, :defaults)
9
+
10
+ def create_klass_struct
11
+ @result = IncludeOptions.new
12
+ end
13
+
14
+ def allowed(value)
15
+ @result.allowed = value
16
+ end
17
+
18
+ def defaults(value)
19
+ @result.defaults = value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+ require 'request_handler/builder/multipart_resource_builder'
5
+
6
+ module RequestHandler
7
+ module Builder
8
+ class MultipartBuilder < Base
9
+ def create_klass_struct
10
+ @result = OpenStruct.new
11
+ end
12
+
13
+ def resource(name, &block)
14
+ @result[name.to_sym] = build_multipart_resource(&block)
15
+ end
16
+
17
+ def build_multipart_resource(&block)
18
+ Docile.dsl_eval(MultipartResourceBuilder.new, &block).build
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'request_handler/builder/base'
4
+
5
+ module RequestHandler
6
+ module Builder
7
+ class MultipartResourceBuilder < Base
8
+ MultipartResource = Struct.new(:required, :schema, :type, :options)
9
+
10
+ def create_klass_struct
11
+ @result = MultipartResource.new
12
+ end
13
+
14
+ def type(value)
15
+ @result.type = value
16
+ end
17
+
18
+ def required(value)
19
+ @result.required = value
20
+ end
21
+
22
+ def resource(name, &block)
23
+ @result[name.to_sym] = build_multipart_resource(&block)
24
+ end
25
+
26
+ def schema(value)
27
+ @result.schema = value
28
+ end
29
+
30
+ def options(value)
31
+ @result.options = value
32
+ end
33
+ end
34
+ end
35
+ end