grape 1.6.0 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +9 -1
  5. data/UPGRADING.md +4 -4
  6. data/lib/grape/api.rb +12 -0
  7. data/lib/grape/dsl/headers.rb +5 -2
  8. data/lib/grape/dsl/helpers.rb +1 -1
  9. data/lib/grape/middleware/auth/dsl.rb +7 -1
  10. data/lib/grape/middleware/base.rb +1 -1
  11. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  12. data/lib/grape/validations/validators/all_or_none.rb +7 -5
  13. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  14. data/lib/grape/validations/validators/as.rb +7 -5
  15. data/lib/grape/validations/validators/at_least_one_of.rb +6 -4
  16. data/lib/grape/validations/validators/base.rb +73 -71
  17. data/lib/grape/validations/validators/coerce.rb +63 -75
  18. data/lib/grape/validations/validators/default.rb +36 -34
  19. data/lib/grape/validations/validators/exactly_one_of.rb +8 -6
  20. data/lib/grape/validations/validators/except_values.rb +13 -11
  21. data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
  22. data/lib/grape/validations/validators/mutual_exclusion.rb +7 -5
  23. data/lib/grape/validations/validators/presence.rb +6 -4
  24. data/lib/grape/validations/validators/regexp.rb +7 -5
  25. data/lib/grape/validations/validators/same_as.rb +17 -15
  26. data/lib/grape/validations/validators/values.rb +59 -57
  27. data/lib/grape/validations.rb +6 -0
  28. data/lib/grape/version.rb +1 -1
  29. data/lib/grape.rb +2 -0
  30. data/spec/grape/api/custom_validations_spec.rb +77 -46
  31. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  32. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  33. data/spec/grape/api/invalid_format_spec.rb +2 -0
  34. data/spec/grape/api/recognize_path_spec.rb +1 -1
  35. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  36. data/spec/grape/api_remount_spec.rb +16 -15
  37. data/spec/grape/api_spec.rb +317 -193
  38. data/spec/grape/dsl/callbacks_spec.rb +1 -0
  39. data/spec/grape/dsl/headers_spec.rb +39 -9
  40. data/spec/grape/dsl/helpers_spec.rb +3 -2
  41. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  42. data/spec/grape/dsl/logger_spec.rb +16 -18
  43. data/spec/grape/dsl/middleware_spec.rb +1 -0
  44. data/spec/grape/dsl/parameters_spec.rb +1 -0
  45. data/spec/grape/dsl/request_response_spec.rb +1 -0
  46. data/spec/grape/dsl/routing_spec.rb +9 -6
  47. data/spec/grape/endpoint/declared_spec.rb +12 -12
  48. data/spec/grape/endpoint_spec.rb +59 -50
  49. data/spec/grape/entity_spec.rb +13 -13
  50. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  51. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  52. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  53. data/spec/grape/exceptions/validation_spec.rb +5 -3
  54. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  55. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  56. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  57. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  58. data/spec/grape/loading_spec.rb +8 -8
  59. data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
  60. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  61. data/spec/grape/middleware/base_spec.rb +24 -15
  62. data/spec/grape/middleware/error_spec.rb +1 -0
  63. data/spec/grape/middleware/exception_spec.rb +111 -161
  64. data/spec/grape/middleware/formatter_spec.rb +25 -4
  65. data/spec/grape/middleware/globals_spec.rb +7 -4
  66. data/spec/grape/middleware/stack_spec.rb +11 -11
  67. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  68. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  69. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  70. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  71. data/spec/grape/middleware/versioner_spec.rb +1 -1
  72. data/spec/grape/parser_spec.rb +4 -0
  73. data/spec/grape/path_spec.rb +52 -52
  74. data/spec/grape/presenters/presenter_spec.rb +7 -6
  75. data/spec/grape/request_spec.rb +6 -4
  76. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  77. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  78. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  79. data/spec/grape/util/stackable_values_spec.rb +7 -5
  80. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  81. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  82. data/spec/grape/validations/params_scope_spec.rb +9 -7
  83. data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
  84. data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
  85. data/spec/grape/validations/types_spec.rb +8 -8
  86. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  87. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  88. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  89. data/spec/grape/validations/validators/coerce_spec.rb +10 -12
  90. data/spec/grape/validations/validators/default_spec.rb +72 -78
  91. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  92. data/spec/grape/validations/validators/except_values_spec.rb +1 -1
  93. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  94. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  95. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  96. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  97. data/spec/grape/validations/validators/values_spec.rb +172 -171
  98. data/spec/grape/validations_spec.rb +45 -16
  99. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  100. data/spec/integration/multi_json/json_spec.rb +1 -1
  101. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  102. data/spec/shared/versioning_examples.rb +10 -7
  103. data/spec/spec_helper.rb +11 -1
  104. metadata +102 -102
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7af0abe5fd1cb203ceda93732e74ded372552f7a859c6a3c6b847d1ac31c9c97
4
- data.tar.gz: 103a38ad4d41eccbfef3240cd8b04fe17f2bc080a4265e4353b43076ce03fb15
3
+ metadata.gz: d182a6dfa2a571345d24a6a2b7286b4a2b34eeedc6570334ba2259fdda59faac
4
+ data.tar.gz: c365091e871e7ad78dd46dc0aab52cdd41d1e5ddb5a46503fcf0020af45f4324
5
5
  SHA512:
6
- metadata.gz: 8c8fb085cbaa5ea150e072a54e98546f4336966871225ae5587d70d115da62d420e1f67b2459f83c39c5d29717f311e93d09e0440dd4bf4a75d1f1cec7573022
7
- data.tar.gz: c0f6eb027e3f43c309c59643ceb28c8f7d783466c0663f3b65e93be52a0c3148123110d9aa81dda842027ace7f0f319519b5cdc1fec7102d65811a84fbc2b2ed
6
+ metadata.gz: 539fdf761a5058dfcb3bab993a7fac3c7223ec06e0b828e102cb52095ac79f63668ebab1c1c4b47bf16984990c94f9a291537e7b2a1359626736b7abdd2c34ec
7
+ data.tar.gz: 2b30d941ab114aab53c4f4630742adedd037856ecc63b65f87b0df506349a13eed092964d9f53c003774006e74b9800043178b2ad2e6c55b0d5d42f6039a7e71
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ### 1.6.2 (2021/12/30)
2
+
3
+ #### Features
4
+
5
+ #### Fixes
6
+
7
+ * [#2219](https://github.com/ruby-grape/grape/pull/2219): Revert the changes for autoloading provided in 1.6.1 - [@dm1try](https://github.com/dm1try).
8
+
9
+ ### 1.6.1 (2021/12/28)
10
+
11
+ #### Features
12
+
13
+ * [#2196](https://github.com/ruby-grape/grape/pull/2196): Add support for `passwords_hashed` param for `digest_auth` - [@lHydra](https://github.com/lhydra).
14
+ * [#2208](https://github.com/ruby-grape/grape/pull/2208): Added Rails 7 support - [@ericproulx](https://github.com/ericproulx).
15
+
16
+ #### Fixes
17
+
18
+ * [#2206](https://github.com/ruby-grape/grape/pull/2206): Require main active_support lib before any of its extension definitions - [@annih](https://github.com/Annih).
19
+ * [#2193](https://github.com/ruby-grape/grape/pull/2193): Fixed the broken ruby-head NoMethodError spec - [@Jack12816](https://github.com/Jack12816).
20
+ * [#2192](https://github.com/ruby-grape/grape/pull/2192): Memoize the result of Grape::Middleware::Base#response - [@Jack12816](https://github.com/Jack12816).
21
+ * [#2200](https://github.com/ruby-grape/grape/pull/2200): Add validators module to all validators - [@ericproulx](https://github.com/ericproulx).
22
+ * [#2202](https://github.com/ruby-grape/grape/pull/2202): Fix random mock spec error - [@ericproulx](https://github.com/ericproulx).
23
+ * [#2203](https://github.com/ruby-grape/grape/pull/2203): Add rubocop-rspec - [@ericproulx](https://github.com/ericproulx).
24
+ * [#2207](https://github.com/ruby-grape/grape/pull/2207): Autoload Validations/Validators - [@ericproulx](https://github.com/ericproulx).
25
+ * [#2209](https://github.com/ruby-grape/grape/pull/2209): Autoload Validations/Types - [@ericproulx](https://github.com/ericproulx).
26
+
1
27
  ### 1.6.0 (2021/10/04)
2
28
 
3
29
  #### Features
data/CONTRIBUTING.md CHANGED
@@ -35,6 +35,7 @@ bundle exec rake
35
35
  Run tests against all supported versions of Rails.
36
36
 
37
37
  ```
38
+ gem install appraisal
38
39
  appraisal install
39
40
  appraisal rake spec
40
41
  ```
@@ -118,7 +119,7 @@ Go back to your pull request after a few minutes and see whether it passed muste
118
119
 
119
120
  #### Be Patient
120
121
 
121
- It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
122
+ It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang in there!
122
123
 
123
124
  #### Thank You
124
125
 
data/README.md CHANGED
@@ -158,7 +158,7 @@ content negotiation, versioning and much more.
158
158
 
159
159
  ## Stable Release
160
160
 
161
- You're reading the documentation for the stable release of Grape, **1.6.0**.
161
+ You're reading the documentation for the stable release of Grape, **1.6.2**.
162
162
  Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
163
163
 
164
164
  ## Project Resources
@@ -3296,12 +3296,20 @@ http_basic do |username, password|
3296
3296
  end
3297
3297
  ```
3298
3298
 
3299
+ Digest auth supports clear-text passwords and password hashes.
3300
+
3299
3301
  ```ruby
3300
3302
  http_digest({ realm: 'Test Api', opaque: 'app secret' }) do |username|
3301
3303
  # lookup the user's password here
3302
3304
  end
3303
3305
  ```
3304
3306
 
3307
+ ```ruby
3308
+ http_digest(realm: { realm: 'Test Api', opaque: 'app secret', passwords_hashed: true }) do |username|
3309
+ # lookup the user's password hash here
3310
+ end
3311
+ ```
3312
+
3305
3313
  ### Register custom middleware for authentication
3306
3314
 
3307
3315
  Grape can use custom Middleware for authentication. How to implement these
data/UPGRADING.md CHANGED
@@ -27,7 +27,7 @@ declared(params, include_missing: false)
27
27
  # actual => { b: '5' } (uncasted, unvalidated, <= 1.5.3)
28
28
  ```
29
29
 
30
- Another implication of this change is the dependent parameter resolution. Prior to 1.6.0 the following code produced an `Grape::Exceptions::UnknownParameter` because `:a` was replace by `:b`:
30
+ Another implication of this change is the dependent parameter resolution. Prior to 1.6.0 the following code produced a `Grape::Exceptions::UnknownParameter` because `:a` was replaced by `:b`:
31
31
 
32
32
  ```ruby
33
33
  params do
@@ -47,7 +47,7 @@ See [#2189](https://github.com/ruby-grape/grape/pull/2189) for more information.
47
47
  #### Nil value and coercion
48
48
 
49
49
  Prior to 1.2.5 version passing a `nil` value for a parameter with a custom coercer would invoke the coercer, and not passing a parameter would not invoke it.
50
- This behavior was not tested or documented. Version 1.3.0 quietly changed this behavior, in such that `nil` values skipped the coercion. Version 1.5.3 fixes and documents this as follows:
50
+ This behavior was not tested or documented. Version 1.3.0 quietly changed this behavior, in that `nil` values skipped the coercion. Version 1.5.3 fixes and documents this as follows:
51
51
 
52
52
  ```ruby
53
53
  class Api < Grape::API
@@ -197,13 +197,13 @@ end
197
197
 
198
198
  #### Nil values for structures
199
199
 
200
- Nil values always been a special case when dealing with types especially with the following structures:
200
+ Nil values have always been a special case when dealing with types, especially with the following structures:
201
201
 
202
202
  - Array
203
203
  - Hash
204
204
  - Set
205
205
 
206
- The behavior for these structures has change through out the latest releases. For example:
206
+ The behavior for these structures has changed throughout the latest releases. For example:
207
207
 
208
208
  ```ruby
209
209
  class Api < Grape::API
data/lib/grape/api.rb CHANGED
@@ -10,6 +10,18 @@ module Grape
10
10
  # Class methods that we want to call on the API rather than on the API object
11
11
  NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile! inherited]).freeze
12
12
 
13
+ class Boolean
14
+ def self.build(val)
15
+ return nil if val != true && val != false
16
+
17
+ new
18
+ end
19
+ end
20
+
21
+ class Instance
22
+ Boolean = Grape::API::Boolean
23
+ end
24
+
13
25
  class << self
14
26
  attr_accessor :base_instance, :instances
15
27
 
@@ -3,8 +3,11 @@
3
3
  module Grape
4
4
  module DSL
5
5
  module Headers
6
- # Set an individual header or retrieve
7
- # all headers that have been set.
6
+ # This method has four responsibilities:
7
+ # 1. Set a specifc header value by key
8
+ # 2. Retrieve a specifc header value by key
9
+ # 3. Retrieve all headers that have been set
10
+ # 4. Delete a specifc header key-value pair
8
11
  def header(key = nil, val = nil)
9
12
  if key
10
13
  val ? header[key.to_s] = val : header.delete(key.to_s)
@@ -68,7 +68,7 @@ module Grape
68
68
  def define_boolean_in_mod(mod)
69
69
  return if defined? mod::Boolean
70
70
 
71
- mod.const_set('Boolean', Grape::API::Boolean)
71
+ mod.const_set(:Boolean, Grape::API::Boolean)
72
72
  end
73
73
 
74
74
  def inject_api_helpers_to_mod(mod, &block)
@@ -32,7 +32,13 @@ module Grape
32
32
 
33
33
  def http_digest(options = {}, &block)
34
34
  options[:realm] ||= 'API Authorization'
35
- options[:opaque] ||= 'secret'
35
+
36
+ if options[:realm].respond_to?(:values_at)
37
+ options[:realm][:opaque] ||= 'secret'
38
+ else
39
+ options[:opaque] ||= 'secret'
40
+ end
41
+
36
42
  auth :http_digest, options, &block
37
43
  end
38
44
  end
@@ -60,7 +60,7 @@ module Grape
60
60
  def response
61
61
  return @app_response if @app_response.is_a?(Rack::Response)
62
62
 
63
- Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
63
+ @app_response = Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
64
64
  end
65
65
 
66
66
  def content_type_for(format)
@@ -65,7 +65,7 @@ module Grape
65
65
  end
66
66
  end
67
67
 
68
- define_method 'to_hash' do
68
+ define_method :to_hash do
69
69
  merge_hash = {}
70
70
  setting_name.each_key { |k| merge_hash[k] = send("#{k}_context").to_hash }
71
71
 
@@ -4,12 +4,14 @@ require 'grape/validations/validators/multiple_params_base'
4
4
 
5
5
  module Grape
6
6
  module Validations
7
- class AllOrNoneOfValidator < MultipleParamsBase
8
- def validate_params!(params)
9
- keys = keys_in_common(params)
10
- return if keys.empty? || keys.length == all_keys.length
7
+ module Validators
8
+ class AllOrNoneOfValidator < MultipleParamsBase
9
+ def validate_params!(params)
10
+ keys = keys_in_common(params)
11
+ return if keys.empty? || keys.length == all_keys.length
11
12
 
12
- raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:all_or_none))
13
+ raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:all_or_none))
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -2,16 +2,18 @@
2
2
 
3
3
  module Grape
4
4
  module Validations
5
- class AllowBlankValidator < Base
6
- def validate_param!(attr_name, params)
7
- return if (options_key?(:value) ? @option[:value] : @option) || !params.is_a?(Hash)
5
+ module Validators
6
+ class AllowBlankValidator < Base
7
+ def validate_param!(attr_name, params)
8
+ return if (options_key?(:value) ? @option[:value] : @option) || !params.is_a?(Hash)
8
9
 
9
- value = params[attr_name]
10
- value = value.strip if value.respond_to?(:strip)
10
+ value = params[attr_name]
11
+ value = value.strip if value.respond_to?(:strip)
11
12
 
12
- return if value == false || value.present?
13
+ return if value == false || value.present?
13
14
 
14
- raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:blank))
15
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:blank))
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Grape
4
4
  module Validations
5
- class AsValidator < Base
6
- # We use a validator for renaming parameters. This is just a marker for
7
- # the parameter scope to handle the renaming. No actual validation
8
- # happens here.
9
- def validate_param!(*); end
5
+ module Validators
6
+ class AsValidator < Base
7
+ # We use a validator for renaming parameters. This is just a marker for
8
+ # the parameter scope to handle the renaming. No actual validation
9
+ # happens here.
10
+ def validate_param!(*); end
11
+ end
10
12
  end
11
13
  end
12
14
  end
@@ -4,11 +4,13 @@ require 'grape/validations/validators/multiple_params_base'
4
4
 
5
5
  module Grape
6
6
  module Validations
7
- class AtLeastOneOfValidator < MultipleParamsBase
8
- def validate_params!(params)
9
- return unless keys_in_common(params).empty?
7
+ module Validators
8
+ class AtLeastOneOfValidator < MultipleParamsBase
9
+ def validate_params!(params)
10
+ return unless keys_in_common(params).empty?
10
11
 
11
- raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:at_least_one))
12
+ raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:at_least_one))
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -2,91 +2,93 @@
2
2
 
3
3
  module Grape
4
4
  module Validations
5
- class Base
6
- attr_reader :attrs
5
+ module Validators
6
+ class Base
7
+ attr_reader :attrs
7
8
 
8
- # Creates a new Validator from options specified
9
- # by a +requires+ or +optional+ directive during
10
- # parameter definition.
11
- # @param attrs [Array] names of attributes to which the Validator applies
12
- # @param options [Object] implementation-dependent Validator options
13
- # @param required [Boolean] attribute(s) are required or optional
14
- # @param scope [ParamsScope] parent scope for this Validator
15
- # @param opts [Array] additional validation options
16
- def initialize(attrs, options, required, scope, *opts)
17
- @attrs = Array(attrs)
18
- @option = options
19
- @required = required
20
- @scope = scope
21
- opts = opts.any? ? opts.shift : {}
22
- @fail_fast = opts.fetch(:fail_fast, false)
23
- @allow_blank = opts.fetch(:allow_blank, false)
24
- end
9
+ # Creates a new Validator from options specified
10
+ # by a +requires+ or +optional+ directive during
11
+ # parameter definition.
12
+ # @param attrs [Array] names of attributes to which the Validator applies
13
+ # @param options [Object] implementation-dependent Validator options
14
+ # @param required [Boolean] attribute(s) are required or optional
15
+ # @param scope [ParamsScope] parent scope for this Validator
16
+ # @param opts [Array] additional validation options
17
+ def initialize(attrs, options, required, scope, *opts)
18
+ @attrs = Array(attrs)
19
+ @option = options
20
+ @required = required
21
+ @scope = scope
22
+ opts = opts.any? ? opts.shift : {}
23
+ @fail_fast = opts.fetch(:fail_fast, false)
24
+ @allow_blank = opts.fetch(:allow_blank, false)
25
+ end
25
26
 
26
- # Validates a given request.
27
- # @note Override #validate! unless you need to access the entire request.
28
- # @param request [Grape::Request] the request currently being handled
29
- # @raise [Grape::Exceptions::Validation] if validation failed
30
- # @return [void]
31
- def validate(request)
32
- return unless @scope.should_validate?(request.params)
27
+ # Validates a given request.
28
+ # @note Override #validate! unless you need to access the entire request.
29
+ # @param request [Grape::Request] the request currently being handled
30
+ # @raise [Grape::Exceptions::Validation] if validation failed
31
+ # @return [void]
32
+ def validate(request)
33
+ return unless @scope.should_validate?(request.params)
33
34
 
34
- validate!(request.params)
35
- end
35
+ validate!(request.params)
36
+ end
36
37
 
37
- # Validates a given parameter hash.
38
- # @note Override #validate if you need to access the entire request.
39
- # @param params [Hash] parameters to validate
40
- # @raise [Grape::Exceptions::Validation] if validation failed
41
- # @return [void]
42
- def validate!(params)
43
- attributes = SingleAttributeIterator.new(self, @scope, params)
44
- # we collect errors inside array because
45
- # there may be more than one error per field
46
- array_errors = []
38
+ # Validates a given parameter hash.
39
+ # @note Override #validate if you need to access the entire request.
40
+ # @param params [Hash] parameters to validate
41
+ # @raise [Grape::Exceptions::Validation] if validation failed
42
+ # @return [void]
43
+ def validate!(params)
44
+ attributes = SingleAttributeIterator.new(self, @scope, params)
45
+ # we collect errors inside array because
46
+ # there may be more than one error per field
47
+ array_errors = []
47
48
 
48
- attributes.each do |val, attr_name, empty_val, skip_value|
49
- next if skip_value
50
- next if !@scope.required? && empty_val
51
- next unless @scope.meets_dependency?(val, params)
49
+ attributes.each do |val, attr_name, empty_val, skip_value|
50
+ next if skip_value
51
+ next if !@scope.required? && empty_val
52
+ next unless @scope.meets_dependency?(val, params)
52
53
 
53
- begin
54
- validate_param!(attr_name, val) if @required || (val.respond_to?(:key?) && val.key?(attr_name))
55
- rescue Grape::Exceptions::Validation => e
56
- array_errors << e
54
+ begin
55
+ validate_param!(attr_name, val) if @required || (val.respond_to?(:key?) && val.key?(attr_name))
56
+ rescue Grape::Exceptions::Validation => e
57
+ array_errors << e
58
+ end
57
59
  end
58
- end
59
60
 
60
- raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
61
- end
61
+ raise Grape::Exceptions::ValidationArrayErrors.new(array_errors) if array_errors.any?
62
+ end
62
63
 
63
- def self.convert_to_short_name(klass)
64
- ret = klass.name.gsub(/::/, '/')
65
- ret.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
66
- ret.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
67
- ret.tr!('-', '_')
68
- ret.downcase!
69
- File.basename(ret, '_validator')
70
- end
64
+ def self.convert_to_short_name(klass)
65
+ ret = klass.name.gsub(/::/, '/')
66
+ ret.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
67
+ ret.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
68
+ ret.tr!('-', '_')
69
+ ret.downcase!
70
+ File.basename(ret, '_validator')
71
+ end
71
72
 
72
- def self.inherited(klass)
73
- return unless klass.name.present?
73
+ def self.inherited(klass)
74
+ return unless klass.name.present?
74
75
 
75
- Validations.register_validator(convert_to_short_name(klass), klass)
76
- end
76
+ Validations.register_validator(convert_to_short_name(klass), klass)
77
+ end
77
78
 
78
- def message(default_key = nil)
79
- options = instance_variable_get(:@option)
80
- options_key?(:message) ? options[:message] : default_key
81
- end
79
+ def message(default_key = nil)
80
+ options = instance_variable_get(:@option)
81
+ options_key?(:message) ? options[:message] : default_key
82
+ end
82
83
 
83
- def options_key?(key, options = nil)
84
- options = instance_variable_get(:@option) if options.nil?
85
- options.respond_to?(:key?) && options.key?(key) && !options[key].nil?
86
- end
84
+ def options_key?(key, options = nil)
85
+ options = instance_variable_get(:@option) if options.nil?
86
+ options.respond_to?(:key?) && options.key?(key) && !options[key].nil?
87
+ end
87
88
 
88
- def fail_fast?
89
- @fail_fast
89
+ def fail_fast?
90
+ @fail_fast
91
+ end
90
92
  end
91
93
  end
92
94
  end
@@ -1,86 +1,74 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Grape
4
- class API
5
- class Boolean
6
- def self.build(val)
7
- return nil if val != true && val != false
8
-
9
- new
10
- end
11
- end
12
-
13
- class Instance
14
- Boolean = Grape::API::Boolean
15
- end
16
- end
17
-
18
4
  module Validations
19
- class CoerceValidator < Base
20
- def initialize(attrs, options, required, scope, **opts)
21
- super
22
-
23
- @converter = if type.is_a?(Grape::Validations::Types::VariantCollectionCoercer)
24
- type
25
- else
26
- Types.build_coercer(type, method: @option[:method])
27
- end
28
- end
29
-
30
- def validate_param!(attr_name, params)
31
- raise validation_exception(attr_name) unless params.is_a? Hash
32
-
33
- new_value = coerce_value(params[attr_name])
34
-
35
- raise validation_exception(attr_name, new_value.message) unless valid_type?(new_value)
36
-
37
- # Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
38
- # which looses wrappers for hashes and arrays after reassigning values
5
+ module Validators
6
+ class CoerceValidator < Base
7
+ def initialize(attrs, options, required, scope, **opts)
8
+ super
9
+
10
+ @converter = if type.is_a?(Grape::Validations::Types::VariantCollectionCoercer)
11
+ type
12
+ else
13
+ Types.build_coercer(type, method: @option[:method])
14
+ end
15
+ end
16
+
17
+ def validate_param!(attr_name, params)
18
+ raise validation_exception(attr_name) unless params.is_a? Hash
19
+
20
+ new_value = coerce_value(params[attr_name])
21
+
22
+ raise validation_exception(attr_name, new_value.message) unless valid_type?(new_value)
23
+
24
+ # Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
25
+ # which looses wrappers for hashes and arrays after reassigning values
26
+ #
27
+ # h = Hashie::Mash.new(list: [1, 2, 3, 4])
28
+ # => #<Hashie::Mash list=#<Hashie::Array [1, 2, 3, 4]>>
29
+ # list = h.list
30
+ # h[:list] = list
31
+ # h
32
+ # => #<Hashie::Mash list=[1, 2, 3, 4]>
33
+ return if params[attr_name].instance_of?(new_value.class) && params[attr_name] == new_value
34
+
35
+ params[attr_name] = new_value
36
+ end
37
+
38
+ private
39
+
40
+ # @!attribute [r] converter
41
+ # Object that will be used for parameter coercion and type checking.
39
42
  #
40
- # h = Hashie::Mash.new(list: [1, 2, 3, 4])
41
- # => #<Hashie::Mash list=#<Hashie::Array [1, 2, 3, 4]>>
42
- # list = h.list
43
- # h[:list] = list
44
- # h
45
- # => #<Hashie::Mash list=[1, 2, 3, 4]>
46
- return if params[attr_name].instance_of?(new_value.class) && params[attr_name] == new_value
47
-
48
- params[attr_name] = new_value
49
- end
50
-
51
- private
52
-
53
- # @!attribute [r] converter
54
- # Object that will be used for parameter coercion and type checking.
55
- #
56
- # See {Types.build_coercer}
57
- #
58
- # @return [Object]
59
- attr_reader :converter
60
-
61
- def valid_type?(val)
62
- !val.is_a?(Types::InvalidValue)
63
- end
43
+ # See {Types.build_coercer}
44
+ #
45
+ # @return [Object]
46
+ attr_reader :converter
64
47
 
65
- def coerce_value(val)
66
- converter.call(val)
67
- # Some custom types might fail, so it should be treated as an invalid value
68
- rescue StandardError
69
- Types::InvalidValue.new
70
- end
48
+ def valid_type?(val)
49
+ !val.is_a?(Types::InvalidValue)
50
+ end
71
51
 
72
- # Type to which the parameter will be coerced.
73
- #
74
- # @return [Class]
75
- def type
76
- @option[:type].is_a?(Hash) ? @option[:type][:value] : @option[:type]
77
- end
52
+ def coerce_value(val)
53
+ converter.call(val)
54
+ # Some custom types might fail, so it should be treated as an invalid value
55
+ rescue StandardError
56
+ Types::InvalidValue.new
57
+ end
78
58
 
79
- def validation_exception(attr_name, custom_msg = nil)
80
- Grape::Exceptions::Validation.new(
81
- params: [@scope.full_name(attr_name)],
82
- message: custom_msg || message(:coerce)
83
- )
59
+ # Type to which the parameter will be coerced.
60
+ #
61
+ # @return [Class]
62
+ def type
63
+ @option[:type].is_a?(Hash) ? @option[:type][:value] : @option[:type]
64
+ end
65
+
66
+ def validation_exception(attr_name, custom_msg = nil)
67
+ Grape::Exceptions::Validation.new(
68
+ params: [@scope.full_name(attr_name)],
69
+ message: custom_msg || message(:coerce)
70
+ )
71
+ end
84
72
  end
85
73
  end
86
74
  end