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
@@ -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