request_handler 1.3.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile +2 -0
- data/README.md +167 -29
- data/lib/request_handler/base.rb +27 -33
- data/lib/request_handler/base_parser.rb +9 -0
- data/lib/request_handler/builder/base.rb +23 -0
- data/lib/request_handler/builder/body_builder.rb +27 -0
- data/lib/request_handler/builder/fieldsets_builder.rb +28 -0
- data/lib/request_handler/builder/fieldsets_resource_builder.rb +17 -0
- data/lib/request_handler/builder/filter_builder.rb +31 -0
- data/lib/request_handler/builder/include_options_builder.rb +23 -0
- data/lib/request_handler/builder/multipart_builder.rb +22 -0
- data/lib/request_handler/builder/multipart_resource_builder.rb +35 -0
- data/lib/request_handler/builder/options_builder.rb +88 -0
- data/lib/request_handler/builder/page_builder.rb +30 -0
- data/lib/request_handler/builder/page_resource_builder.rb +23 -0
- data/lib/request_handler/builder/query_builder.rb +23 -0
- data/lib/request_handler/builder/sort_options_builder.rb +23 -0
- data/lib/request_handler/concerns/config_helper.rb +25 -0
- data/lib/request_handler/config.rb +33 -0
- data/lib/request_handler/fieldsets_parser.rb +5 -4
- data/lib/request_handler/include_option_parser.rb +2 -2
- data/lib/request_handler/multipart_parser.rb +8 -11
- data/lib/request_handler/option_parser.rb +1 -1
- data/lib/request_handler/page_parser.rb +19 -10
- data/lib/request_handler/schema_parser.rb +8 -4
- data/lib/request_handler/sort_option_parser.rb +2 -2
- data/lib/request_handler/validation/definition_engine.rb +2 -1
- data/lib/request_handler/validation/dry_engine.rb +24 -16
- data/lib/request_handler/version.rb +1 -1
- data/lib/request_handler.rb +7 -22
- data/request_handler.gemspec +2 -4
- metadata +33 -44
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'request_handler/builder/base'
|
4
|
+
require 'request_handler/builder/page_builder'
|
5
|
+
require 'request_handler/builder/include_options_builder'
|
6
|
+
require 'request_handler/builder/sort_options_builder'
|
7
|
+
require 'request_handler/builder/filter_builder'
|
8
|
+
require 'request_handler/builder/query_builder'
|
9
|
+
require 'request_handler/builder/body_builder'
|
10
|
+
require 'request_handler/builder/multipart_builder'
|
11
|
+
require 'request_handler/builder/fieldsets_builder'
|
12
|
+
|
13
|
+
module RequestHandler
|
14
|
+
module Builder
|
15
|
+
class OptionsBuilder < Base
|
16
|
+
Options = Struct.new(:page, :include_options, :sort_options, :filter, :query, :body,
|
17
|
+
:multipart, :fieldsets)
|
18
|
+
|
19
|
+
def create_klass_struct
|
20
|
+
@result = Options.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def page(&block)
|
24
|
+
@result.page = build_page(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def include_options(&block)
|
28
|
+
@result.include_options = build_include_options(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def sort_options(&block)
|
32
|
+
@result.sort_options = build_sort_options(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def filter(&block)
|
36
|
+
@result.filter = build_filter(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def query(&block)
|
40
|
+
@result.query = build_query(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def body(&block)
|
44
|
+
@result.body = build_body(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def multipart(&block)
|
48
|
+
@result.multipart = build_multipart(&block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def fieldsets(&block)
|
52
|
+
@result.fieldsets = build_fieldsets(&block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_page(&block)
|
56
|
+
Docile.dsl_eval(PageBuilder.new, &block).build
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_include_options(&block)
|
60
|
+
Docile.dsl_eval(IncludeOptionsBuilder.new, &block).build
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_sort_options(&block)
|
64
|
+
Docile.dsl_eval(SortOptionsBuilder.new, &block).build
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_filter(&block)
|
68
|
+
Docile.dsl_eval(FilterBuilder.new, &block).build
|
69
|
+
end
|
70
|
+
|
71
|
+
def build_query(&block)
|
72
|
+
Docile.dsl_eval(QueryBuilder.new, &block).build
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_body(&block)
|
76
|
+
Docile.dsl_eval(BodyBuilder.new, &block).build
|
77
|
+
end
|
78
|
+
|
79
|
+
def build_multipart(&block)
|
80
|
+
Docile.dsl_eval(MultipartBuilder.new, &block).build
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_fieldsets(&block)
|
84
|
+
Docile.dsl_eval(FieldsetsBuilder.new, &block).build
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'request_handler/builder/base'
|
4
|
+
require 'request_handler/builder/page_resource_builder'
|
5
|
+
|
6
|
+
module RequestHandler
|
7
|
+
module Builder
|
8
|
+
class PageBuilder < Base
|
9
|
+
def create_klass_struct
|
10
|
+
@result = OpenStruct.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_size(value)
|
14
|
+
@result.default_size = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def max_size(value)
|
18
|
+
@result.max_size = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def resource(name, &block)
|
22
|
+
@result[name.to_sym] = build_page_resource(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_page_resource(&block)
|
26
|
+
Docile.dsl_eval(PageResourceBuilder.new, &block).build
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
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 PageResourceBuilder < Base
|
8
|
+
PageResource = Struct.new(:default_size, :max_size)
|
9
|
+
|
10
|
+
def create_klass_struct
|
11
|
+
@result = PageResource.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def default_size(value)
|
15
|
+
@result.default_size = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def max_size(value)
|
19
|
+
@result.max_size = 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 QueryBuilder < Base
|
8
|
+
Query = Struct.new(:schema, :options)
|
9
|
+
|
10
|
+
def create_klass_struct
|
11
|
+
@result = Query.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 SortOptionsBuilder < Base
|
8
|
+
SortOptions = Struct.new(:allowed, :defaults)
|
9
|
+
|
10
|
+
def create_klass_struct
|
11
|
+
@result = SortOptions.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,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RequestHandler
|
4
|
+
module Concerns
|
5
|
+
module ConfigHelper
|
6
|
+
def lookup!(hash, key)
|
7
|
+
lookup(hash, key) || (raise NoConfigAvailableError, key.to_sym => 'is not configured')
|
8
|
+
end
|
9
|
+
|
10
|
+
def lookup(config, key)
|
11
|
+
config.dig(*symbolize_key(key))
|
12
|
+
end
|
13
|
+
|
14
|
+
def symbolize_key(key)
|
15
|
+
key.split('.').map(&:to_sym)
|
16
|
+
end
|
17
|
+
|
18
|
+
def deep_to_h(obj)
|
19
|
+
obj.to_h.transform_values do |v|
|
20
|
+
v.is_a?(OpenStruct) || v.is_a?(Struct) ? deep_to_h(v) : v
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'docile'
|
4
|
+
|
5
|
+
module RequestHandler
|
6
|
+
class Config
|
7
|
+
def initialize(&block)
|
8
|
+
@config = Docile.dsl_eval(RequestHandler::Builder::OptionsBuilder.new, &block).build
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :config
|
12
|
+
|
13
|
+
def lookup!(key)
|
14
|
+
lookup(key) || (raise NoConfigAvailableError, key.to_sym => 'is not configured')
|
15
|
+
end
|
16
|
+
|
17
|
+
def lookup(key)
|
18
|
+
@config.dig(*symbolize_key(key))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def symbolize_key(key)
|
24
|
+
key.split('.').map(&:to_sym)
|
25
|
+
end
|
26
|
+
|
27
|
+
def deep_to_h(obj)
|
28
|
+
obj.to_h.transform_values do |v|
|
29
|
+
v.is_a?(OpenStruct) || v.is_a?(Struct) ? deep_to_h(v) : v
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -7,9 +7,10 @@ module RequestHandler
|
|
7
7
|
def initialize(params:, allowed: {}, required: [])
|
8
8
|
@params = params
|
9
9
|
allowed.reject! { |_k, v| v == false }
|
10
|
-
allowed.
|
10
|
+
allowed.each_pair do |_key, value|
|
11
11
|
raise InternalArgumentError, allowed: 'must be a Schema or a Boolean' unless
|
12
|
-
RequestHandler.
|
12
|
+
RequestHandler.configuration.validation_engine.valid_schema?(value) ||
|
13
|
+
value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
13
14
|
end
|
14
15
|
@allowed = allowed
|
15
16
|
raise InternalArgumentError, required: 'must be an Array' unless required.is_a?(Array)
|
@@ -39,7 +40,7 @@ module RequestHandler
|
|
39
40
|
if allowed[type] == true
|
40
41
|
option.to_sym
|
41
42
|
else
|
42
|
-
RequestHandler.
|
43
|
+
RequestHandler.configuration.validation_engine.validate!(option, allowed[type]).output.to_sym
|
43
44
|
end
|
44
45
|
rescue Validation::Error
|
45
46
|
raise FieldsetsParamsError, [{ code: 'INVALID_QUERY_PARAMETER',
|
@@ -55,7 +56,7 @@ module RequestHandler
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def raise_invalid_field_option(type)
|
58
|
-
return if allowed.
|
59
|
+
return if allowed.dig(type)
|
59
60
|
raise OptionNotAllowedError, [
|
60
61
|
{
|
61
62
|
code: 'INVALID_QUERY_PARAMETER',
|
@@ -13,9 +13,9 @@ module RequestHandler
|
|
13
13
|
|
14
14
|
def allowed_options(options)
|
15
15
|
options.map do |option|
|
16
|
-
option.gsub!('.', ::RequestHandler.separator)
|
16
|
+
option.gsub!('.', ::RequestHandler.configuration.separator)
|
17
17
|
begin
|
18
|
-
RequestHandler.
|
18
|
+
RequestHandler.configuration.validation_engine.validate!(option, allowed_options_type).output.to_sym
|
19
19
|
rescue Validation::Error
|
20
20
|
raise_error('OPTION_NOT_ALLOWED', "#{option} is not an allowed include option", OptionNotAllowedError)
|
21
21
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'request_handler/error'
|
4
|
+
require 'request_handler/base_parser'
|
4
5
|
require 'request_handler/schema_parser'
|
5
6
|
require 'request_handler/document_parser'
|
6
7
|
|
7
8
|
module RequestHandler
|
8
|
-
class MultipartsParser
|
9
|
+
class MultipartsParser < BaseParser
|
9
10
|
def initialize(request:, multipart_config:)
|
10
11
|
@request = request
|
11
12
|
@params = request.params
|
@@ -14,10 +15,10 @@ module RequestHandler
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def run
|
17
|
-
multipart_config.each_with_object({}) do |(name, config),
|
18
|
+
deep_to_h(multipart_config).each_with_object({}) do |(name, config), indexed_parts|
|
18
19
|
validate_presence!(name) if config[:required]
|
19
20
|
next if params[name.to_s].nil?
|
20
|
-
|
21
|
+
indexed_parts[name] = parse_part(name.to_s)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -38,7 +39,7 @@ module RequestHandler
|
|
38
39
|
|
39
40
|
def parse_part(name)
|
40
41
|
params[name].fetch(:tempfile) { raise MultipartParamsError, [{ multipart_file: 'missing' }] }
|
41
|
-
if lookup("#{name}.schema")
|
42
|
+
if lookup(multipart_config, "#{name}.schema")
|
42
43
|
parse_data(name)
|
43
44
|
else
|
44
45
|
params[name]
|
@@ -47,12 +48,12 @@ module RequestHandler
|
|
47
48
|
|
48
49
|
def parse_data(name)
|
49
50
|
data = load_json(name)
|
50
|
-
type = lookup("#{name}.type")
|
51
|
+
type = lookup(multipart_config, "#{name}.type")
|
51
52
|
DocumentParser.new(
|
52
53
|
type: type,
|
53
54
|
document: data,
|
54
|
-
schema: lookup("#{name}.schema"),
|
55
|
-
schema_options: execute_options(lookup("#{name}.options"))
|
55
|
+
schema: lookup(multipart_config, "#{name}.schema"),
|
56
|
+
schema_options: execute_options(lookup(multipart_config, "#{name}.options"))
|
56
57
|
).run
|
57
58
|
end
|
58
59
|
|
@@ -69,10 +70,6 @@ module RequestHandler
|
|
69
70
|
params[name][:tempfile]
|
70
71
|
end
|
71
72
|
|
72
|
-
def lookup(key)
|
73
|
-
multipart_config.lookup!(key)
|
74
|
-
end
|
75
|
-
|
76
73
|
def execute_options(options)
|
77
74
|
return {} if options.nil?
|
78
75
|
return options unless options.respond_to?(:call)
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'request_handler/error'
|
4
|
+
require 'request_handler/base_parser'
|
5
|
+
|
4
6
|
module RequestHandler
|
5
|
-
class PageParser
|
7
|
+
class PageParser < BaseParser
|
6
8
|
def initialize(params:, page_config:)
|
7
9
|
missing_arguments = []
|
8
10
|
missing_arguments << { params: 'is missing' } if params.nil?
|
@@ -14,11 +16,10 @@ module RequestHandler
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def run
|
17
|
-
|
18
|
-
cfg = config.keys.reduce(base) do |memo, key|
|
19
|
+
cfg = deep_to_h(config).keys.reduce(base_page) do |memo, key|
|
19
20
|
next memo if TOP_LEVEL_PAGE_KEYS.include?(key)
|
20
|
-
memo.merge!("#{key}#{
|
21
|
-
"#{key}#{
|
21
|
+
memo.merge!("#{key}#{separator}number".to_sym => extract_number(prefix: key),
|
22
|
+
"#{key}#{separator}size".to_sym => extract_size(prefix: key))
|
22
23
|
end
|
23
24
|
check_for_missing_options(cfg)
|
24
25
|
cfg
|
@@ -29,10 +30,14 @@ module RequestHandler
|
|
29
30
|
TOP_LEVEL_PAGE_KEYS = Set.new(%i[default_size max_size])
|
30
31
|
attr_reader :page_options, :config
|
31
32
|
|
33
|
+
def base_page
|
34
|
+
{ number: extract_number, size: extract_size }
|
35
|
+
end
|
36
|
+
|
32
37
|
def check_for_missing_options(config)
|
33
38
|
missing_arguments = page_options.keys - config.keys.map(&:to_s)
|
34
39
|
return if missing_arguments.empty?
|
35
|
-
missing_arguments.map! { |e| e.gsub(
|
40
|
+
missing_arguments.map! { |e| e.gsub(separator, '.') }
|
36
41
|
warn 'client sent unknown option ' + missing_arguments.to_s unless missing_arguments.empty?
|
37
42
|
end
|
38
43
|
|
@@ -93,11 +98,11 @@ module RequestHandler
|
|
93
98
|
|
94
99
|
def lookup_nested_config_key(key, prefix)
|
95
100
|
key = prefix ? "#{prefix}.#{key}" : key
|
96
|
-
|
101
|
+
lookup(config, key)
|
97
102
|
end
|
98
103
|
|
99
104
|
def lookup_nested_params_key(key, prefix)
|
100
|
-
key = prefix ? "#{prefix}#{
|
105
|
+
key = prefix ? "#{prefix}#{separator}#{key}" : key
|
101
106
|
page_options.fetch(key, nil)
|
102
107
|
end
|
103
108
|
|
@@ -105,12 +110,16 @@ module RequestHandler
|
|
105
110
|
::RequestHandler.configuration.logger.warn(message)
|
106
111
|
end
|
107
112
|
|
108
|
-
def raise_no_default_size(prefix, sep =
|
113
|
+
def raise_no_default_size(prefix, sep = separator)
|
109
114
|
raise NoConfigAvailableError, :"#{prefix}#{sep}size" => 'has no default_size'
|
110
115
|
end
|
111
116
|
|
112
|
-
def raise_not_positive(prefix, key, sep =
|
117
|
+
def raise_not_positive(prefix, key, sep = separator)
|
113
118
|
raise InternalArgumentError, :"#{prefix}#{sep}#{key}" => 'must be a positive Integer'
|
114
119
|
end
|
120
|
+
|
121
|
+
def separator
|
122
|
+
::RequestHandler.configuration.separator
|
123
|
+
end
|
115
124
|
end
|
116
125
|
end
|
@@ -8,7 +8,7 @@ module RequestHandler
|
|
8
8
|
missing_arguments << { schema: 'is missing' } if schema.nil?
|
9
9
|
missing_arguments << { schema_options: 'is missing' } if schema_options.nil?
|
10
10
|
raise MissingArgumentError, missing_arguments unless missing_arguments.empty?
|
11
|
-
raise InternalArgumentError, schema: 'must be a Schema' unless
|
11
|
+
raise InternalArgumentError, schema: 'must be a Schema' unless validation_engine.valid_schema?(schema)
|
12
12
|
@schema = schema
|
13
13
|
@schema_options = schema_options
|
14
14
|
end
|
@@ -23,7 +23,7 @@ module RequestHandler
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def validate(data, schema:)
|
26
|
-
|
26
|
+
validation_engine.validate(data, schema, options: schema_options)
|
27
27
|
end
|
28
28
|
|
29
29
|
def validation_failure?(validator)
|
@@ -46,11 +46,11 @@ module RequestHandler
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def error(path, element, failure)
|
49
|
-
schema_pointer =
|
49
|
+
schema_pointer = validation_engine.error_pointer(failure) || (path + [element]).join('/')
|
50
50
|
{
|
51
51
|
schema_pointer: schema_pointer,
|
52
52
|
element: element,
|
53
|
-
message:
|
53
|
+
message: validation_engine.error_message(failure)
|
54
54
|
}
|
55
55
|
end
|
56
56
|
|
@@ -77,6 +77,10 @@ module RequestHandler
|
|
77
77
|
memo
|
78
78
|
end
|
79
79
|
|
80
|
+
def validation_engine
|
81
|
+
RequestHandler.configuration.validation_engine
|
82
|
+
end
|
83
|
+
|
80
84
|
attr_reader :schema, :schema_options
|
81
85
|
end
|
82
86
|
end
|
@@ -20,7 +20,7 @@ module RequestHandler
|
|
20
20
|
def parse_options(options)
|
21
21
|
options.map do |option|
|
22
22
|
name, order = parse_option(option)
|
23
|
-
name.gsub!('.', ::RequestHandler.separator)
|
23
|
+
name.gsub!('.', ::RequestHandler.configuration.separator)
|
24
24
|
allowed_option(name)
|
25
25
|
SortOption.new(name, order)
|
26
26
|
end
|
@@ -36,7 +36,7 @@ module RequestHandler
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def allowed_option(name)
|
39
|
-
RequestHandler.
|
39
|
+
RequestHandler.configuration.validation_engine.validate!(name, allowed_options_type).output
|
40
40
|
rescue Validation::Error
|
41
41
|
raise OptionNotAllowedError, [jsonapi_error("#{name} is not an allowed sort option")]
|
42
42
|
end
|
@@ -18,7 +18,8 @@ module RequestHandler
|
|
18
18
|
|
19
19
|
def self.validate!(value, schema, options: {})
|
20
20
|
validate(value, schema, options).tap do |result|
|
21
|
-
|
21
|
+
valid = result.respond_to?(:valid?) ? result.valid? : result.success?
|
22
|
+
raise Validation::Error unless valid
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -7,35 +7,43 @@ module RequestHandler
|
|
7
7
|
module Validation
|
8
8
|
class DryEngine < Engine
|
9
9
|
def self.valid_schema?(schema)
|
10
|
-
schema
|
10
|
+
schema_instance?(schema) || schema_class?(schema)
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.validate(value, schema, options: {})
|
14
|
-
value = value.deep_symbolize_keys if
|
15
|
-
|
16
|
-
result = if options.empty?
|
17
|
-
schema.call(value)
|
18
|
-
else
|
19
|
-
schema.with(options).call(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
to_result(result)
|
14
|
+
value = value.deep_symbolize_keys if value.is_a?(Hash)
|
15
|
+
to_result(call_schema(value, schema, options))
|
23
16
|
rescue Dry::Types::ConstraintError => e
|
24
17
|
Result.new(output: nil, errors: { '' => e })
|
25
18
|
end
|
26
19
|
|
20
|
+
def self.call_schema(value, schema, options)
|
21
|
+
if options.empty?
|
22
|
+
schema_instance?(schema) ? schema.call(value) : schema.new.call(value)
|
23
|
+
else
|
24
|
+
schema_instance?(schema) ? schema.with(options).call(value) : schema.new(options).call(value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.schema_instance?(schema)
|
29
|
+
schema.respond_to?(:call)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.schema_class?(schema)
|
33
|
+
schema.respond_to?(:schema)
|
34
|
+
end
|
35
|
+
|
27
36
|
def self.validate!(value, schema, options: {})
|
28
37
|
validate(value, schema, options).tap do |result|
|
29
|
-
|
38
|
+
valid = result.respond_to?(:valid?) ? result.valid? : result.success?
|
39
|
+
raise Validation::Error unless valid
|
30
40
|
end
|
31
41
|
end
|
32
42
|
|
33
43
|
def self.to_result(result)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Result.new(output: result, errors: {})
|
38
|
-
end
|
44
|
+
output = result.respond_to?(:to_h) ? result.to_h : result
|
45
|
+
errors = result.respond_to?(:errors) ? result.errors.to_h : {}
|
46
|
+
Result.new(output: output, errors: errors)
|
39
47
|
end
|
40
48
|
|
41
49
|
def self.error_message(validation_error)
|
data/lib/request_handler.rb
CHANGED
@@ -3,32 +3,17 @@
|
|
3
3
|
require 'request_handler/version'
|
4
4
|
require 'request_handler/base'
|
5
5
|
require 'request_handler/validation/dry_engine'
|
6
|
-
require 'confstruct'
|
7
|
-
require 'dry-validation'
|
8
6
|
require 'multi_json'
|
9
7
|
require 'logger'
|
8
|
+
require 'gem_config'
|
10
9
|
|
11
10
|
module RequestHandler
|
12
|
-
|
13
|
-
def configure(&block)
|
14
|
-
configuration.configure(&block)
|
15
|
-
end
|
11
|
+
include GemConfig::Base
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
raise_jsonapi_errors false
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def separator
|
27
|
-
configuration.separator
|
28
|
-
end
|
29
|
-
|
30
|
-
def engine
|
31
|
-
configuration.validation_engine
|
32
|
-
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
|
33
18
|
end
|
34
19
|
end
|
data/request_handler.gemspec
CHANGED
@@ -23,12 +23,10 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.add_dependency '
|
27
|
-
spec.add_dependency 'dry-types', '~> 0.11', '>= 0.11.0'
|
28
|
-
|
29
|
-
spec.add_dependency 'confstruct', '~> 1.0.2'
|
26
|
+
spec.add_dependency 'docile', '~> 1.3'
|
30
27
|
spec.add_dependency 'multi_json', '~> 1.12'
|
31
28
|
spec.add_dependency 'activesupport', '> 4.0'
|
29
|
+
spec.add_dependency 'gem_config', '~> 0.3 '
|
32
30
|
|
33
31
|
spec.add_development_dependency 'bundler'
|
34
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|