grape 1.2.4 → 1.2.5
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 +18 -4
- data/README.md +144 -4
- data/grape.gemspec +3 -1
- data/lib/grape.rb +94 -66
- data/lib/grape/api.rb +46 -4
- data/lib/grape/api/instance.rb +23 -12
- data/lib/grape/dsl/desc.rb +11 -2
- data/lib/grape/dsl/validations.rb +4 -3
- data/lib/grape/eager_load.rb +18 -0
- data/lib/grape/endpoint.rb +3 -3
- data/lib/grape/error_formatter.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +4 -2
- data/lib/grape/formatter.rb +1 -1
- data/lib/grape/middleware/auth/base.rb +2 -4
- data/lib/grape/middleware/base.rb +2 -0
- data/lib/grape/middleware/helpers.rb +10 -0
- data/lib/grape/parser.rb +1 -1
- data/lib/grape/util/base_inheritable.rb +34 -0
- data/lib/grape/util/inheritable_values.rb +5 -25
- data/lib/grape/util/lazy_block.rb +25 -0
- data/lib/grape/util/lazy_value.rb +5 -0
- data/lib/grape/util/reverse_stackable_values.rb +7 -36
- data/lib/grape/util/stackable_values.rb +19 -22
- data/lib/grape/validations/attributes_iterator.rb +5 -3
- data/lib/grape/validations/multiple_attributes_iterator.rb +11 -0
- data/lib/grape/validations/params_scope.rb +12 -12
- data/lib/grape/validations/single_attribute_iterator.rb +13 -0
- data/lib/grape/validations/validator_factory.rb +6 -11
- data/lib/grape/validations/validators/all_or_none.rb +6 -13
- data/lib/grape/validations/validators/at_least_one_of.rb +5 -13
- data/lib/grape/validations/validators/base.rb +11 -10
- data/lib/grape/validations/validators/coerce.rb +4 -0
- data/lib/grape/validations/validators/default.rb +1 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +6 -23
- data/lib/grape/validations/validators/multiple_params_base.rb +14 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +6 -18
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/defines_boolean_in_params_spec.rb +37 -0
- data/spec/grape/api_remount_spec.rb +158 -0
- data/spec/grape/api_spec.rb +72 -0
- data/spec/grape/endpoint_spec.rb +1 -1
- data/spec/grape/exceptions/base_spec.rb +4 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +6 -4
- data/spec/grape/integration/rack_spec.rb +22 -6
- data/spec/grape/middleware/base_spec.rb +8 -0
- data/spec/grape/middleware/formatter_spec.rb +11 -1
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +29 -0
- data/spec/grape/validations/params_scope_spec.rb +13 -0
- data/spec/grape/validations/single_attribute_iterator_spec.rb +33 -0
- data/spec/grape/validations/validators/all_or_none_spec.rb +138 -30
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +173 -29
- data/spec/grape/validations/validators/coerce_spec.rb +6 -2
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +202 -38
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +184 -27
- data/spec/grape/validations_spec.rb +32 -20
- metadata +103 -115
- data/Appraisals +0 -28
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile.lock +0 -232
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_3.gemfile.lock +0 -288
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_4.gemfile.lock +0 -280
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_5.gemfile.lock +0 -312
- data/gemfiles/rails_edge.gemfile +0 -35
- data/pkg/grape-1.2.0.gem +0 -0
- data/pkg/grape-1.2.1.gem +0 -0
- data/pkg/grape-1.2.3.gem +0 -0
@@ -1,45 +1,16 @@
|
|
1
|
+
require_relative 'stackable_values'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Util
|
3
|
-
class ReverseStackableValues
|
4
|
-
|
5
|
-
attr_accessor :new_values
|
6
|
-
|
7
|
-
def initialize(inherited_values = {})
|
8
|
-
@inherited_values = inherited_values
|
9
|
-
@new_values = {}
|
10
|
-
end
|
5
|
+
class ReverseStackableValues < StackableValues
|
6
|
+
protected
|
11
7
|
|
12
|
-
def
|
8
|
+
def concat_values(inherited_value, new_value)
|
13
9
|
[].tap do |value|
|
14
|
-
value.concat(
|
15
|
-
value.concat(
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def []=(name, value)
|
20
|
-
@new_values[name] ||= []
|
21
|
-
@new_values[name].push value
|
22
|
-
end
|
23
|
-
|
24
|
-
def delete(key)
|
25
|
-
new_values.delete key
|
26
|
-
end
|
27
|
-
|
28
|
-
def keys
|
29
|
-
(@new_values.keys + @inherited_values.keys).sort.uniq
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_hash
|
33
|
-
keys.each_with_object({}) do |key, result|
|
34
|
-
result[key] = self[key]
|
10
|
+
value.concat(new_value)
|
11
|
+
value.concat(inherited_value)
|
35
12
|
end
|
36
13
|
end
|
37
|
-
|
38
|
-
def initialize_copy(other)
|
39
|
-
super
|
40
|
-
self.inherited_values = other.inherited_values
|
41
|
-
self.new_values = other.new_values.dup
|
42
|
-
end
|
43
14
|
end
|
44
15
|
end
|
45
16
|
end
|
@@ -1,23 +1,25 @@
|
|
1
|
+
require_relative 'base_inheritable'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Util
|
3
|
-
class StackableValues
|
4
|
-
attr_accessor :inherited_values
|
5
|
-
attr_accessor :new_values
|
5
|
+
class StackableValues < BaseInheritable
|
6
6
|
attr_reader :frozen_values
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
|
10
|
-
|
8
|
+
def initialize(*_args)
|
9
|
+
super
|
10
|
+
|
11
11
|
@frozen_values = {}
|
12
12
|
end
|
13
13
|
|
14
14
|
def [](name)
|
15
15
|
return @frozen_values[name] if @frozen_values.key? name
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
inherited_value = @inherited_values[name]
|
18
|
+
new_value = @new_values[name] || []
|
19
|
+
|
20
|
+
return new_value unless inherited_value
|
21
|
+
|
22
|
+
concat_values(inherited_value, new_value)
|
21
23
|
end
|
22
24
|
|
23
25
|
def []=(name, value)
|
@@ -26,14 +28,6 @@ module Grape
|
|
26
28
|
@new_values[name].push value
|
27
29
|
end
|
28
30
|
|
29
|
-
def delete(key)
|
30
|
-
new_values.delete key
|
31
|
-
end
|
32
|
-
|
33
|
-
def keys
|
34
|
-
(@new_values.keys + @inherited_values.keys).sort.uniq
|
35
|
-
end
|
36
|
-
|
37
31
|
def to_hash
|
38
32
|
keys.each_with_object({}) do |key, result|
|
39
33
|
result[key] = self[key]
|
@@ -44,10 +38,13 @@ module Grape
|
|
44
38
|
@frozen_values[key] = self[key].freeze
|
45
39
|
end
|
46
40
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
protected
|
42
|
+
|
43
|
+
def concat_values(inherited_value, new_value)
|
44
|
+
[].tap do |value|
|
45
|
+
value.concat(inherited_value)
|
46
|
+
value.concat(new_value)
|
47
|
+
end
|
51
48
|
end
|
52
49
|
end
|
53
50
|
end
|
@@ -41,11 +41,13 @@ module Grape
|
|
41
41
|
@scope.index = index
|
42
42
|
end
|
43
43
|
|
44
|
-
@attrs
|
45
|
-
yield resource_params, attr_name, inside_array
|
46
|
-
end
|
44
|
+
yield_attributes(resource_params, @attrs, &block)
|
47
45
|
end
|
48
46
|
end
|
47
|
+
|
48
|
+
def yield_attributes(_resource_params, _attrs)
|
49
|
+
raise NotImplementedError
|
50
|
+
end
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -76,7 +76,7 @@ module Grape
|
|
76
76
|
def full_name(name, index: nil)
|
77
77
|
if nested?
|
78
78
|
# Find our containing element's name, and append ours.
|
79
|
-
|
79
|
+
"#{@parent.full_name(@element)}#{brackets(@index || index)}#{brackets(name)}"
|
80
80
|
elsif lateral?
|
81
81
|
# Find the name of the element as if it was at the same nesting level
|
82
82
|
# as our parent. We need to forward our index upward to achieve this.
|
@@ -184,14 +184,12 @@ module Grape
|
|
184
184
|
raise Grape::Exceptions::UnsupportedGroupTypeError.new unless Grape::Validations::Types.group?(type)
|
185
185
|
end
|
186
186
|
|
187
|
-
opts = attrs[1] || { type: Array }
|
188
|
-
|
189
187
|
self.class.new(
|
190
188
|
api: @api,
|
191
|
-
element: attrs.first,
|
189
|
+
element: attrs[1][:as] || attrs.first,
|
192
190
|
parent: self,
|
193
191
|
optional: optional,
|
194
|
-
type:
|
192
|
+
type: type || Array,
|
195
193
|
&block
|
196
194
|
)
|
197
195
|
end
|
@@ -412,13 +410,15 @@ module Grape
|
|
412
410
|
|
413
411
|
raise Grape::Exceptions::UnknownValidator.new(type) unless validator_class
|
414
412
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
413
|
+
validator_options = {
|
414
|
+
attributes: attrs,
|
415
|
+
options: options,
|
416
|
+
required: doc_attrs[:required],
|
417
|
+
params_scope: self,
|
418
|
+
opts: opts,
|
419
|
+
validator_class: validator_class
|
420
|
+
}
|
421
|
+
@api.namespace_stackable(:validations, validator_options)
|
422
422
|
end
|
423
423
|
|
424
424
|
def validate_value_coercion(coerce_type, *values_list)
|
@@ -1,17 +1,12 @@
|
|
1
1
|
module Grape
|
2
2
|
module Validations
|
3
3
|
class ValidatorFactory
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@validator_class.new(@options[:attributes],
|
11
|
-
@options[:options],
|
12
|
-
@options[:required],
|
13
|
-
@options[:params_scope],
|
14
|
-
@options[:opts])
|
4
|
+
def self.create_validator(**options)
|
5
|
+
options[:validator_class].new(options[:attributes],
|
6
|
+
options[:options],
|
7
|
+
options[:required],
|
8
|
+
options[:params_scope],
|
9
|
+
options[:opts])
|
15
10
|
end
|
16
11
|
end
|
17
12
|
end
|
@@ -1,19 +1,12 @@
|
|
1
|
+
require 'grape/validations/validators/multiple_params_base'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
|
-
require 'grape/validations/validators/multiple_params_base'
|
4
5
|
class AllOrNoneOfValidator < MultipleParamsBase
|
5
|
-
def
|
6
|
-
|
7
|
-
if
|
8
|
-
|
9
|
-
end
|
10
|
-
params
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def only_subset_present
|
16
|
-
scoped_params.any? { |resource_params| !keys_in_common(resource_params).empty? && keys_in_common(resource_params).length < attrs.length }
|
6
|
+
def validate_params!(params)
|
7
|
+
keys = keys_in_common(params)
|
8
|
+
return if keys.empty? || keys.length == all_keys.length
|
9
|
+
raise Grape::Exceptions::Validation, params: all_keys, message: message(:all_or_none)
|
17
10
|
end
|
18
11
|
end
|
19
12
|
end
|
@@ -1,19 +1,11 @@
|
|
1
|
+
require 'grape/validations/validators/multiple_params_base'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
|
-
require 'grape/validations/validators/multiple_params_base'
|
4
5
|
class AtLeastOneOfValidator < MultipleParamsBase
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
raise Grape::Exceptions::Validation, params: all_keys, message: message(:at_least_one)
|
9
|
-
end
|
10
|
-
params
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def no_exclusive_params_are_present
|
16
|
-
scoped_params.any? { |resource_params| keys_in_common(resource_params).empty? }
|
6
|
+
def validate_params!(params)
|
7
|
+
return unless keys_in_common(params).empty?
|
8
|
+
raise Grape::Exceptions::Validation, params: all_keys, message: message(:at_least_one)
|
17
9
|
end
|
18
10
|
end
|
19
11
|
end
|
@@ -35,18 +35,19 @@ module Grape
|
|
35
35
|
# @raise [Grape::Exceptions::Validation] if validation failed
|
36
36
|
# @return [void]
|
37
37
|
def validate!(params)
|
38
|
-
attributes =
|
38
|
+
attributes = SingleAttributeIterator.new(self, @scope, params)
|
39
|
+
# we collect errors inside array because
|
40
|
+
# there may be more than one error per field
|
39
41
|
array_errors = []
|
42
|
+
|
40
43
|
attributes.each do |resource_params, attr_name|
|
41
44
|
next if !@scope.required? && resource_params.empty?
|
42
|
-
next unless @required || (resource_params.respond_to?(:key?) && resource_params.key?(attr_name))
|
43
45
|
next unless @scope.meets_dependency?(resource_params, params)
|
44
|
-
|
45
46
|
begin
|
46
|
-
|
47
|
+
if @required || resource_params.respond_to?(:key?) && resource_params.key?(attr_name)
|
48
|
+
validate_param!(attr_name, resource_params)
|
49
|
+
end
|
47
50
|
rescue Grape::Exceptions::Validation => e
|
48
|
-
# we collect errors inside array because
|
49
|
-
# there may be more than one error per field
|
50
51
|
array_errors << e
|
51
52
|
end
|
52
53
|
end
|
@@ -56,10 +57,10 @@ module Grape
|
|
56
57
|
|
57
58
|
def self.convert_to_short_name(klass)
|
58
59
|
ret = klass.name.gsub(/::/, '/')
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
ret.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
61
|
+
ret.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
62
|
+
ret.tr!('-', '_')
|
63
|
+
ret.downcase!
|
63
64
|
File.basename(ret, '_validator')
|
64
65
|
end
|
65
66
|
|
@@ -18,7 +18,7 @@ module Grape
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def validate!(params)
|
21
|
-
attrs =
|
21
|
+
attrs = SingleAttributeIterator.new(self, @scope, params)
|
22
22
|
attrs.each do |resource_params, attr_name|
|
23
23
|
if resource_params.is_a?(Hash) && resource_params[attr_name].nil?
|
24
24
|
validate_param!(attr_name, resource_params)
|
@@ -1,28 +1,11 @@
|
|
1
|
+
require 'grape/validations/validators/multiple_params_base'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
if scope_requires_params && none_of_restricted_params_is_present
|
8
|
-
raise Grape::Exceptions::Validation, params: all_keys, message: message(:exactly_one)
|
9
|
-
end
|
10
|
-
params
|
11
|
-
end
|
12
|
-
|
13
|
-
def message(default_key = nil)
|
14
|
-
options = instance_variable_get(:@option)
|
15
|
-
if options_key?(:message)
|
16
|
-
(options_key?(default_key, options[:message]) ? options[:message][default_key] : options[:message])
|
17
|
-
else
|
18
|
-
default_key
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def none_of_restricted_params_is_present
|
25
|
-
scoped_params.any? { |resource_params| keys_in_common(resource_params).empty? }
|
5
|
+
class ExactlyOneOfValidator < MultipleParamsBase
|
6
|
+
def validate_params!(params)
|
7
|
+
return if keys_in_common(params).length == 1
|
8
|
+
raise Grape::Exceptions::Validation, params: all_keys, message: message(:exactly_one)
|
26
9
|
end
|
27
10
|
end
|
28
11
|
end
|
@@ -1,26 +1,30 @@
|
|
1
1
|
module Grape
|
2
2
|
module Validations
|
3
3
|
class MultipleParamsBase < Base
|
4
|
-
attr_reader :scoped_params
|
5
|
-
|
6
4
|
def validate!(params)
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
attributes = MultipleAttributesIterator.new(self, @scope, params)
|
6
|
+
array_errors = []
|
10
7
|
|
11
|
-
|
8
|
+
attributes.each do |resource_params|
|
9
|
+
begin
|
10
|
+
validate_params!(resource_params)
|
11
|
+
rescue Grape::Exceptions::Validation => e
|
12
|
+
array_errors << e
|
13
|
+
end
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
@scope.required? || scoped_params.any? { |param| param.respond_to?(:any?) && param.any? }
|
16
|
+
raise Grape::Exceptions::ValidationArrayErrors, array_errors if array_errors.any?
|
15
17
|
end
|
16
18
|
|
19
|
+
private
|
20
|
+
|
17
21
|
def keys_in_common(resource_params)
|
18
22
|
return [] unless resource_params.is_a?(Hash)
|
19
|
-
|
23
|
+
all_keys & resource_params.keys.map! { |attr| @scope.full_name(attr) }
|
20
24
|
end
|
21
25
|
|
22
26
|
def all_keys
|
23
|
-
attrs.map(
|
27
|
+
attrs.map { |attr| @scope.full_name(attr) }
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
@@ -1,24 +1,12 @@
|
|
1
|
+
require 'grape/validations/validators/multiple_params_base'
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Validations
|
3
|
-
require 'grape/validations/validators/multiple_params_base'
|
4
5
|
class MutualExclusionValidator < MultipleParamsBase
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
if two_or_more_exclusive_params_are_present
|
10
|
-
raise Grape::Exceptions::Validation, params: processing_keys_in_common, message: message(:mutual_exclusion)
|
11
|
-
end
|
12
|
-
params
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def two_or_more_exclusive_params_are_present
|
18
|
-
scoped_params.any? do |resource_params|
|
19
|
-
@processing_keys_in_common = keys_in_common(resource_params)
|
20
|
-
@processing_keys_in_common.length > 1
|
21
|
-
end
|
6
|
+
def validate_params!(params)
|
7
|
+
keys = keys_in_common(params)
|
8
|
+
return if keys.length <= 1
|
9
|
+
raise Grape::Exceptions::Validation, params: keys, message: message(:mutual_exclusion)
|
22
10
|
end
|
23
11
|
end
|
24
12
|
end
|