grape 1.5.2 → 1.7.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.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +152 -21
  5. data/UPGRADING.md +86 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +2 -19
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +8 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +21 -36
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +2 -2
  28. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  29. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  30. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  31. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  32. data/lib/grape/exceptions/validation.rb +1 -6
  33. data/lib/grape/formatter/json.rb +1 -0
  34. data/lib/grape/formatter/serializable_hash.rb +2 -1
  35. data/lib/grape/formatter/xml.rb +1 -0
  36. data/lib/grape/locale/en.yml +9 -8
  37. data/lib/grape/middleware/auth/dsl.rb +7 -2
  38. data/lib/grape/middleware/base.rb +3 -1
  39. data/lib/grape/middleware/error.rb +2 -2
  40. data/lib/grape/middleware/formatter.rb +4 -4
  41. data/lib/grape/middleware/stack.rb +2 -2
  42. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  43. data/lib/grape/middleware/versioner/header.rb +6 -4
  44. data/lib/grape/middleware/versioner/param.rb +1 -0
  45. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  46. data/lib/grape/middleware/versioner/path.rb +2 -0
  47. data/lib/grape/parser/json.rb +1 -1
  48. data/lib/grape/parser/xml.rb +1 -1
  49. data/lib/grape/path.rb +1 -0
  50. data/lib/grape/request.rb +5 -0
  51. data/lib/grape/router/pattern.rb +1 -1
  52. data/lib/grape/router/route.rb +2 -2
  53. data/lib/grape/router.rb +6 -0
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +137 -78
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/json.rb +2 -1
  64. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  65. data/lib/grape/validations/types/set_coercer.rb +0 -2
  66. data/lib/grape/validations/types.rb +98 -30
  67. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  68. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  69. data/lib/grape/validations/validators/as_validator.rb +14 -0
  70. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  71. data/lib/grape/validations/validators/base.rb +82 -70
  72. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  73. data/lib/grape/validations/validators/default_validator.rb +51 -0
  74. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  75. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  76. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  77. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  78. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  79. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  80. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  81. data/lib/grape/validations/validators/values_validator.rb +88 -0
  82. data/lib/grape/validations.rb +16 -6
  83. data/lib/grape/version.rb +1 -1
  84. data/lib/grape.rb +70 -29
  85. data/spec/grape/api/custom_validations_spec.rb +116 -45
  86. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  87. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  88. data/spec/grape/api/documentation_spec.rb +59 -0
  89. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  90. data/spec/grape/api/instance_spec.rb +0 -1
  91. data/spec/grape/api/invalid_format_spec.rb +2 -2
  92. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  93. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  94. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  95. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  96. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  97. data/spec/grape/api/recognize_path_spec.rb +1 -3
  98. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  99. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  100. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  101. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  102. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  103. data/spec/grape/api_remount_spec.rb +16 -16
  104. data/spec/grape/api_spec.rb +527 -224
  105. data/spec/grape/config_spec.rb +0 -2
  106. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  107. data/spec/grape/dsl/configuration_spec.rb +0 -2
  108. data/spec/grape/dsl/desc_spec.rb +0 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +98 -57
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +0 -2
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +24 -17
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +27 -8
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
  169. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  170. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  171. data/spec/grape/validations/params_scope_spec.rb +361 -96
  172. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  173. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  174. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  175. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  176. data/spec/grape/validations/types_spec.rb +36 -10
  177. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  178. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  179. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  180. data/spec/grape/validations/validators/coerce_spec.rb +99 -24
  181. data/spec/grape/validations/validators/default_spec.rb +72 -80
  182. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  183. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  184. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  185. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  186. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  187. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  188. data/spec/grape/validations/validators/values_spec.rb +182 -179
  189. data/spec/grape/validations_spec.rb +149 -80
  190. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  191. data/spec/integration/multi_json/json_spec.rb +1 -3
  192. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  193. data/spec/shared/versioning_examples.rb +12 -9
  194. data/spec/spec_helper.rb +21 -6
  195. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  196. metadata +125 -115
  197. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  198. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  199. data/lib/grape/validations/validators/as.rb +0 -16
  200. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  201. data/lib/grape/validations/validators/coerce.rb +0 -91
  202. data/lib/grape/validations/validators/default.rb +0 -48
  203. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  204. data/lib/grape/validations/validators/except_values.rb +0 -22
  205. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  206. data/lib/grape/validations/validators/presence.rb +0 -12
  207. data/lib/grape/validations/validators/regexp.rb +0 -13
  208. data/lib/grape/validations/validators/same_as.rb +0 -26
  209. data/lib/grape/validations/validators/values.rb +0 -83
  210. data/spec/support/eager_load.rb +0 -19
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class DefaultValidator < Base
6
- def initialize(attrs, options, required, scope, **opts)
7
- @default = options
8
- super
9
- end
10
-
11
- def validate_param!(attr_name, params)
12
- params[attr_name] = if @default.is_a? Proc
13
- @default.call
14
- elsif @default.frozen? || !duplicatable?(@default)
15
- @default
16
- else
17
- duplicate(@default)
18
- end
19
- end
20
-
21
- def validate!(params)
22
- attrs = SingleAttributeIterator.new(self, @scope, params)
23
- attrs.each do |resource_params, attr_name|
24
- next unless @scope.meets_dependency?(resource_params, params)
25
- validate_param!(attr_name, resource_params) if resource_params.is_a?(Hash) && resource_params[attr_name].nil?
26
- end
27
- end
28
-
29
- private
30
-
31
- # return true if we might be able to dup this object
32
- def duplicatable?(obj)
33
- !obj.nil? &&
34
- obj != true &&
35
- obj != false &&
36
- !obj.is_a?(Symbol) &&
37
- !obj.is_a?(Numeric)
38
- end
39
-
40
- # make a best effort to dup the object
41
- def duplicate(obj)
42
- obj.dup
43
- rescue TypeError
44
- obj
45
- end
46
- end
47
- end
48
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'grape/validations/validators/multiple_params_base'
4
-
5
- module Grape
6
- module Validations
7
- class ExactlyOneOfValidator < MultipleParamsBase
8
- def validate_params!(params)
9
- keys = keys_in_common(params)
10
- return if keys.length == 1
11
- raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:exactly_one)) if keys.length.zero?
12
- raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
13
- end
14
- end
15
- end
16
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class ExceptValuesValidator < Base
6
- def initialize(attrs, options, required, scope, **opts)
7
- @except = options.is_a?(Hash) ? options[:value] : options
8
- super
9
- end
10
-
11
- def validate_param!(attr_name, params)
12
- return unless params.respond_to?(:key?) && params.key?(attr_name)
13
-
14
- excepts = @except.is_a?(Proc) ? @except.call : @except
15
- return if excepts.nil?
16
-
17
- param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
18
- raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:except_values)) if param_array.any? { |param| excepts.include?(param) }
19
- end
20
- end
21
- end
22
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'grape/validations/validators/multiple_params_base'
4
-
5
- module Grape
6
- module Validations
7
- class MutualExclusionValidator < MultipleParamsBase
8
- def validate_params!(params)
9
- keys = keys_in_common(params)
10
- return if keys.length <= 1
11
- raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
12
- end
13
- end
14
- end
15
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class PresenceValidator < Base
6
- def validate_param!(attr_name, params)
7
- return if params.respond_to?(:key?) && params.key?(attr_name)
8
- raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:presence))
9
- end
10
- end
11
- end
12
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class RegexpValidator < Base
6
- def validate_param!(attr_name, params)
7
- return unless params.respond_to?(:key?) && params.key?(attr_name)
8
- return if Array.wrap(params[attr_name]).all? { |param| param.nil? || param.to_s.match?((options_key?(:value) ? @option[:value] : @option)) }
9
- raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:regexp))
10
- end
11
- end
12
- end
13
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class SameAsValidator < Base
6
- def validate_param!(attr_name, params)
7
- confirmation = options_key?(:value) ? @option[:value] : @option
8
- return if params[attr_name] == params[confirmation]
9
- raise Grape::Exceptions::Validation.new(
10
- params: [@scope.full_name(attr_name)],
11
- message: build_message
12
- )
13
- end
14
-
15
- private
16
-
17
- def build_message
18
- if options_key?(:message)
19
- @option[:message]
20
- else
21
- format I18n.t(:same_as, scope: 'grape.errors.messages'), parameter: @option
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- class ValuesValidator < Base
6
- def initialize(attrs, options, required, scope, **opts)
7
- if options.is_a?(Hash)
8
- @excepts = options[:except]
9
- @values = options[:value]
10
- @proc = options[:proc]
11
-
12
- warn '[DEPRECATION] The values validator except option is deprecated. ' \
13
- 'Use the except validator instead.' if @excepts
14
-
15
- raise ArgumentError, 'proc must be a Proc' if @proc && !@proc.is_a?(Proc)
16
- warn '[DEPRECATION] The values validator proc option is deprecated. ' \
17
- 'The lambda expression can now be assigned directly to values.' if @proc
18
- else
19
- @excepts = nil
20
- @values = nil
21
- @proc = nil
22
- @values = options
23
- end
24
- super
25
- end
26
-
27
- def validate_param!(attr_name, params)
28
- return unless params.is_a?(Hash)
29
-
30
- val = params[attr_name]
31
-
32
- return if val.nil? && !required_for_root_scope?
33
-
34
- # don't forget that +false.blank?+ is true
35
- return if val != false && val.blank? && @allow_blank
36
-
37
- param_array = val.nil? ? [nil] : Array.wrap(val)
38
-
39
- raise validation_exception(attr_name, except_message) \
40
- unless check_excepts(param_array)
41
-
42
- raise validation_exception(attr_name, message(:values)) \
43
- unless check_values(param_array, attr_name)
44
-
45
- raise validation_exception(attr_name, message(:values)) \
46
- if @proc && !param_array.all? { |param| @proc.call(param) }
47
- end
48
-
49
- private
50
-
51
- def check_values(param_array, attr_name)
52
- values = @values.is_a?(Proc) && @values.arity.zero? ? @values.call : @values
53
- return true if values.nil?
54
- begin
55
- return param_array.all? { |param| values.call(param) } if values.is_a? Proc
56
- rescue StandardError => e
57
- warn "Error '#{e}' raised while validating attribute '#{attr_name}'"
58
- return false
59
- end
60
- param_array.all? { |param| values.include?(param) }
61
- end
62
-
63
- def check_excepts(param_array)
64
- excepts = @excepts.is_a?(Proc) ? @excepts.call : @excepts
65
- return true if excepts.nil?
66
- param_array.none? { |param| excepts.include?(param) }
67
- end
68
-
69
- def except_message
70
- options = instance_variable_get(:@option)
71
- options_key?(:except_message) ? options[:except_message] : message(:except_values)
72
- end
73
-
74
- def required_for_root_scope?
75
- @required && @scope.root?
76
- end
77
-
78
- def validation_exception(attr_name, message)
79
- Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
80
- end
81
- end
82
- end
83
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Grape uses autoload https://api.rubyonrails.org/classes/ActiveSupport/Autoload.html.
4
- # When a class/module get added to the list, ActiveSupport doesn't check whether it really exists.
5
- # This method loads all classes/modules defined via autoload to be sure only existing
6
- # classes/modules were listed.
7
- def eager_load!(scope = Grape)
8
- # get modules
9
- scope.constants.each do |const_name|
10
- const = scope.const_get(const_name)
11
-
12
- next unless const.respond_to?(:eager_load!)
13
-
14
- const.eager_load!
15
-
16
- # check its modules, they might need to be loaded as well.
17
- eager_load!(const)
18
- end
19
- end