grape 1.2.5 → 1.3.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 (253) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +5 -3
  4. data/UPGRADING.md +43 -0
  5. data/grape.gemspec +10 -1
  6. data/lib/grape.rb +2 -2
  7. data/lib/grape/api.rb +2 -0
  8. data/lib/grape/api/helpers.rb +2 -0
  9. data/lib/grape/api/instance.rb +4 -2
  10. data/lib/grape/config.rb +2 -0
  11. data/lib/grape/cookies.rb +2 -0
  12. data/lib/grape/dsl/api.rb +2 -0
  13. data/lib/grape/dsl/callbacks.rb +2 -0
  14. data/lib/grape/dsl/configuration.rb +2 -0
  15. data/lib/grape/dsl/desc.rb +2 -0
  16. data/lib/grape/dsl/headers.rb +2 -0
  17. data/lib/grape/dsl/helpers.rb +3 -1
  18. data/lib/grape/dsl/inside_route.rb +7 -4
  19. data/lib/grape/dsl/logger.rb +2 -0
  20. data/lib/grape/dsl/middleware.rb +2 -0
  21. data/lib/grape/dsl/parameters.rb +4 -2
  22. data/lib/grape/dsl/request_response.rb +4 -2
  23. data/lib/grape/dsl/routing.rb +3 -1
  24. data/lib/grape/dsl/settings.rb +7 -1
  25. data/lib/grape/dsl/validations.rb +2 -0
  26. data/lib/grape/eager_load.rb +2 -0
  27. data/lib/grape/endpoint.rb +13 -7
  28. data/lib/grape/error_formatter.rb +3 -1
  29. data/lib/grape/error_formatter/base.rb +2 -0
  30. data/lib/grape/error_formatter/json.rb +2 -0
  31. data/lib/grape/error_formatter/txt.rb +2 -0
  32. data/lib/grape/error_formatter/xml.rb +2 -0
  33. data/lib/grape/exceptions/base.rb +11 -9
  34. data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
  35. data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
  36. data/lib/grape/exceptions/invalid_formatter.rb +2 -0
  37. data/lib/grape/exceptions/invalid_message_body.rb +2 -0
  38. data/lib/grape/exceptions/invalid_response.rb +2 -0
  39. data/lib/grape/exceptions/invalid_version_header.rb +2 -0
  40. data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
  41. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
  42. data/lib/grape/exceptions/method_not_allowed.rb +2 -0
  43. data/lib/grape/exceptions/missing_group_type.rb +2 -0
  44. data/lib/grape/exceptions/missing_mime_type.rb +2 -0
  45. data/lib/grape/exceptions/missing_option.rb +2 -0
  46. data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
  47. data/lib/grape/exceptions/unknown_options.rb +2 -0
  48. data/lib/grape/exceptions/unknown_parameter.rb +2 -0
  49. data/lib/grape/exceptions/unknown_validator.rb +2 -0
  50. data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
  51. data/lib/grape/exceptions/validation.rb +3 -1
  52. data/lib/grape/exceptions/validation_array_errors.rb +2 -0
  53. data/lib/grape/exceptions/validation_errors.rb +2 -0
  54. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
  55. data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
  56. data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
  57. data/lib/grape/extensions/hash.rb +2 -0
  58. data/lib/grape/extensions/hashie/mash.rb +2 -0
  59. data/lib/grape/formatter.rb +5 -3
  60. data/lib/grape/formatter/json.rb +2 -0
  61. data/lib/grape/formatter/serializable_hash.rb +2 -0
  62. data/lib/grape/formatter/txt.rb +2 -0
  63. data/lib/grape/formatter/xml.rb +2 -0
  64. data/lib/grape/http/headers.rb +23 -17
  65. data/lib/grape/middleware/auth/base.rb +2 -0
  66. data/lib/grape/middleware/auth/dsl.rb +2 -0
  67. data/lib/grape/middleware/auth/strategies.rb +2 -0
  68. data/lib/grape/middleware/auth/strategy_info.rb +2 -0
  69. data/lib/grape/middleware/base.rb +4 -2
  70. data/lib/grape/middleware/error.rb +3 -1
  71. data/lib/grape/middleware/filter.rb +2 -0
  72. data/lib/grape/middleware/formatter.rb +5 -3
  73. data/lib/grape/middleware/globals.rb +2 -0
  74. data/lib/grape/middleware/helpers.rb +2 -0
  75. data/lib/grape/middleware/stack.rb +2 -0
  76. data/lib/grape/middleware/versioner.rb +2 -0
  77. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
  78. data/lib/grape/middleware/versioner/header.rb +2 -0
  79. data/lib/grape/middleware/versioner/param.rb +3 -1
  80. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -0
  81. data/lib/grape/middleware/versioner/path.rb +2 -0
  82. data/lib/grape/namespace.rb +2 -0
  83. data/lib/grape/parser.rb +3 -1
  84. data/lib/grape/parser/json.rb +2 -0
  85. data/lib/grape/parser/xml.rb +2 -0
  86. data/lib/grape/path.rb +2 -0
  87. data/lib/grape/presenters/presenter.rb +2 -0
  88. data/lib/grape/request.rb +3 -1
  89. data/lib/grape/router.rb +11 -6
  90. data/lib/grape/router/attribute_translator.rb +18 -8
  91. data/lib/grape/router/pattern.rb +6 -3
  92. data/lib/grape/router/route.rb +7 -2
  93. data/lib/grape/serve_file/file_body.rb +2 -0
  94. data/lib/grape/serve_file/file_response.rb +2 -0
  95. data/lib/grape/serve_file/sendfile_response.rb +2 -0
  96. data/lib/grape/util/base_inheritable.rb +2 -0
  97. data/lib/grape/util/content_types.rb +2 -0
  98. data/lib/grape/util/endpoint_configuration.rb +2 -0
  99. data/lib/grape/util/env.rb +19 -17
  100. data/lib/grape/util/inheritable_setting.rb +2 -0
  101. data/lib/grape/util/inheritable_values.rb +2 -0
  102. data/lib/grape/util/json.rb +2 -0
  103. data/lib/grape/util/lazy_block.rb +2 -0
  104. data/lib/grape/util/lazy_value.rb +2 -0
  105. data/lib/grape/util/registrable.rb +2 -0
  106. data/lib/grape/util/reverse_stackable_values.rb +2 -0
  107. data/lib/grape/util/stackable_values.rb +3 -0
  108. data/lib/grape/util/strict_hash_configuration.rb +2 -0
  109. data/lib/grape/util/xml.rb +2 -0
  110. data/lib/grape/validations.rb +2 -0
  111. data/lib/grape/validations/attributes_iterator.rb +3 -3
  112. data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
  113. data/lib/grape/validations/params_scope.rb +23 -10
  114. data/lib/grape/validations/single_attribute_iterator.rb +13 -2
  115. data/lib/grape/validations/types.rb +7 -30
  116. data/lib/grape/validations/types/array_coercer.rb +56 -0
  117. data/lib/grape/validations/types/build_coercer.rb +49 -48
  118. data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
  119. data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
  120. data/lib/grape/validations/types/dry_type_coercer.rb +41 -0
  121. data/lib/grape/validations/types/file.rb +10 -9
  122. data/lib/grape/validations/types/json.rb +11 -8
  123. data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
  124. data/lib/grape/validations/types/primitive_coercer.rb +58 -0
  125. data/lib/grape/validations/types/set_coercer.rb +38 -0
  126. data/lib/grape/validations/types/variant_collection_coercer.rb +4 -12
  127. data/lib/grape/validations/validator_factory.rb +2 -0
  128. data/lib/grape/validations/validators/all_or_none.rb +3 -1
  129. data/lib/grape/validations/validators/allow_blank.rb +3 -1
  130. data/lib/grape/validations/validators/as.rb +2 -0
  131. data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
  132. data/lib/grape/validations/validators/base.rb +8 -5
  133. data/lib/grape/validations/validators/coerce.rb +43 -26
  134. data/lib/grape/validations/validators/default.rb +2 -0
  135. data/lib/grape/validations/validators/exactly_one_of.rb +3 -1
  136. data/lib/grape/validations/validators/except_values.rb +3 -1
  137. data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
  138. data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
  139. data/lib/grape/validations/validators/presence.rb +3 -1
  140. data/lib/grape/validations/validators/regexp.rb +3 -1
  141. data/lib/grape/validations/validators/same_as.rb +6 -3
  142. data/lib/grape/validations/validators/values.rb +17 -5
  143. data/lib/grape/version.rb +3 -1
  144. data/spec/grape/api/custom_validations_spec.rb +5 -3
  145. data/spec/grape/api/deeply_included_options_spec.rb +2 -0
  146. data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
  147. data/spec/grape/api/inherited_helpers_spec.rb +2 -0
  148. data/spec/grape/api/instance_spec.rb +54 -0
  149. data/spec/grape/api/invalid_format_spec.rb +2 -0
  150. data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
  151. data/spec/grape/api/nested_helpers_spec.rb +2 -0
  152. data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
  153. data/spec/grape/api/parameters_modification_spec.rb +3 -1
  154. data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
  155. data/spec/grape/api/recognize_path_spec.rb +2 -0
  156. data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
  157. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
  158. data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
  159. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
  160. data/spec/grape/api/shared_helpers_spec.rb +2 -0
  161. data/spec/grape/api_remount_spec.rb +2 -0
  162. data/spec/grape/api_spec.rb +27 -5
  163. data/spec/grape/config_spec.rb +2 -0
  164. data/spec/grape/dsl/callbacks_spec.rb +2 -0
  165. data/spec/grape/dsl/configuration_spec.rb +2 -0
  166. data/spec/grape/dsl/desc_spec.rb +2 -0
  167. data/spec/grape/dsl/headers_spec.rb +2 -0
  168. data/spec/grape/dsl/helpers_spec.rb +4 -2
  169. data/spec/grape/dsl/inside_route_spec.rb +2 -0
  170. data/spec/grape/dsl/logger_spec.rb +2 -0
  171. data/spec/grape/dsl/middleware_spec.rb +2 -0
  172. data/spec/grape/dsl/parameters_spec.rb +2 -0
  173. data/spec/grape/dsl/request_response_spec.rb +2 -0
  174. data/spec/grape/dsl/routing_spec.rb +2 -0
  175. data/spec/grape/dsl/settings_spec.rb +2 -0
  176. data/spec/grape/dsl/validations_spec.rb +2 -0
  177. data/spec/grape/endpoint_spec.rb +3 -1
  178. data/spec/grape/entity_spec.rb +2 -0
  179. data/spec/grape/exceptions/base_spec.rb +3 -1
  180. data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
  181. data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
  182. data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
  183. data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
  184. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
  185. data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
  186. data/spec/grape/exceptions/missing_option_spec.rb +2 -0
  187. data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
  188. data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
  189. data/spec/grape/exceptions/validation_errors_spec.rb +2 -0
  190. data/spec/grape/exceptions/validation_spec.rb +3 -1
  191. data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
  192. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
  193. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
  194. data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
  195. data/spec/grape/integration/rack_sendfile_spec.rb +2 -0
  196. data/spec/grape/integration/rack_spec.rb +3 -1
  197. data/spec/grape/loading_spec.rb +2 -0
  198. data/spec/grape/middleware/auth/base_spec.rb +2 -0
  199. data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
  200. data/spec/grape/middleware/auth/strategies_spec.rb +2 -0
  201. data/spec/grape/middleware/base_spec.rb +2 -0
  202. data/spec/grape/middleware/error_spec.rb +2 -0
  203. data/spec/grape/middleware/exception_spec.rb +3 -1
  204. data/spec/grape/middleware/formatter_spec.rb +17 -10
  205. data/spec/grape/middleware/globals_spec.rb +2 -0
  206. data/spec/grape/middleware/stack_spec.rb +2 -0
  207. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
  208. data/spec/grape/middleware/versioner/header_spec.rb +3 -1
  209. data/spec/grape/middleware/versioner/param_spec.rb +3 -1
  210. data/spec/grape/middleware/versioner/path_spec.rb +3 -1
  211. data/spec/grape/middleware/versioner_spec.rb +2 -0
  212. data/spec/grape/named_api_spec.rb +2 -0
  213. data/spec/grape/parser_spec.rb +7 -5
  214. data/spec/grape/path_spec.rb +2 -0
  215. data/spec/grape/presenters/presenter_spec.rb +2 -0
  216. data/spec/grape/request_spec.rb +2 -0
  217. data/spec/grape/util/inheritable_setting_spec.rb +2 -0
  218. data/spec/grape/util/inheritable_values_spec.rb +2 -0
  219. data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
  220. data/spec/grape/util/stackable_values_spec.rb +3 -1
  221. data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
  222. data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
  223. data/spec/grape/validations/instance_behaivour_spec.rb +4 -2
  224. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
  225. data/spec/grape/validations/params_scope_spec.rb +3 -1
  226. data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
  227. data/spec/grape/validations/types_spec.rb +8 -35
  228. data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
  229. data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
  230. data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
  231. data/spec/grape/validations/validators/coerce_spec.rb +43 -66
  232. data/spec/grape/validations/validators/default_spec.rb +2 -0
  233. data/spec/grape/validations/validators/exactly_one_of_spec.rb +2 -0
  234. data/spec/grape/validations/validators/except_values_spec.rb +3 -1
  235. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
  236. data/spec/grape/validations/validators/presence_spec.rb +30 -0
  237. data/spec/grape/validations/validators/regexp_spec.rb +2 -0
  238. data/spec/grape/validations/validators/same_as_spec.rb +2 -0
  239. data/spec/grape/validations/validators/values_spec.rb +29 -4
  240. data/spec/grape/validations_spec.rb +61 -3
  241. data/spec/integration/multi_json/json_spec.rb +2 -0
  242. data/spec/integration/multi_xml/xml_spec.rb +2 -0
  243. data/spec/shared/versioning_examples.rb +2 -0
  244. data/spec/spec_helper.rb +15 -0
  245. data/spec/support/basic_auth_encode_helpers.rb +2 -0
  246. data/spec/support/content_type_helpers.rb +2 -0
  247. data/spec/support/endpoint_faker.rb +2 -0
  248. data/spec/support/file_streamer.rb +2 -0
  249. data/spec/support/integer_helpers.rb +2 -0
  250. data/spec/support/versioned_helpers.rb +4 -2
  251. metadata +119 -111
  252. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
  253. data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class Base
@@ -17,6 +19,7 @@ module Grape
17
19
  @required = required
18
20
  @scope = scope
19
21
  @fail_fast = opts[:fail_fast] || false
22
+ @allow_blank = opts[:allow_blank] || false
20
23
  end
21
24
 
22
25
  # Validates a given request.
@@ -40,12 +43,12 @@ module Grape
40
43
  # there may be more than one error per field
41
44
  array_errors = []
42
45
 
43
- attributes.each do |resource_params, attr_name|
44
- next if !@scope.required? && resource_params.empty?
45
- next unless @scope.meets_dependency?(resource_params, params)
46
+ attributes.each do |val, attr_name, empty_val|
47
+ next if !@scope.required? && empty_val
48
+ next unless @scope.meets_dependency?(val, params)
46
49
  begin
47
- if @required || resource_params.respond_to?(:key?) && resource_params.key?(attr_name)
48
- validate_param!(attr_name, resource_params)
50
+ if @required || val.respond_to?(:key?) && val.key?(attr_name)
51
+ validate_param!(attr_name, val)
49
52
  end
50
53
  rescue Grape::Exceptions::Validation => e
51
54
  array_errors << e
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  class API
3
- Boolean = Virtus::Attribute::Boolean
5
+ class Boolean
6
+ def self.build(val)
7
+ return nil if val != true && val != false
8
+
9
+ new
10
+ end
11
+ end
4
12
 
5
13
  class Instance
6
- Boolean = Virtus::Attribute::Boolean
14
+ Boolean = Grape::API::Boolean
7
15
  end
8
16
  end
9
17
 
@@ -11,7 +19,12 @@ module Grape
11
19
  class CoerceValidator < Base
12
20
  def initialize(*_args)
13
21
  super
14
- @converter = Types.build_coercer(type, @option[:method])
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
15
28
  end
16
29
 
17
30
  def validate(request)
@@ -19,11 +32,22 @@ module Grape
19
32
  end
20
33
 
21
34
  def validate_param!(attr_name, params)
22
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:coerce) unless params.is_a? Hash
23
- return unless requires_coercion?(params[attr_name])
35
+ raise validation_exception(attr_name) unless params.is_a? Hash
36
+
24
37
  new_value = coerce_value(params[attr_name])
25
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:coerce) unless valid_type?(new_value)
26
- params[attr_name] = new_value
38
+
39
+ raise validation_exception(attr_name) unless valid_type?(new_value)
40
+
41
+ # Don't assign a value if it is identical. It fixes a problem with Hashie::Mash
42
+ # which looses wrappers for hashes and arrays after reassigning values
43
+ #
44
+ # h = Hashie::Mash.new(list: [1, 2, 3, 4])
45
+ # => #<Hashie::Mash list=#<Hashie::Array [1, 2, 3, 4]>>
46
+ # list = h.list
47
+ # h[:list] = list
48
+ # h
49
+ # => #<Hashie::Mash list=[1, 2, 3, 4]>
50
+ params[attr_name] = new_value unless params[attr_name] == new_value
27
51
  end
28
52
 
29
53
  private
@@ -33,31 +57,25 @@ module Grape
33
57
  #
34
58
  # See {Types.build_coercer}
35
59
  #
36
- # @return [Virtus::Attribute]
60
+ # @return [Object]
37
61
  attr_reader :converter
38
62
 
39
63
  def valid_type?(val)
40
- # Special value to denote coercion failure
41
- return false if val.instance_of?(Types::InvalidValue)
42
-
43
- # Allow nil, to ignore when a parameter is absent
44
- return true if val.nil?
45
-
46
- converter.value_coerced? val
64
+ !val.is_a?(Types::InvalidValue)
47
65
  end
48
66
 
49
67
  def coerce_value(val)
50
- # Don't coerce things other than nil to Arrays or Hashes
51
- unless (@option[:method] && !val.nil?) || type.is_a?(Virtus::Attribute)
52
- return val || [] if type == Array
53
- return val || Set.new if type == Set
54
- return val || {} if type == Hash
68
+ # define default values for structures, the dry-types lib which is used
69
+ # for coercion doesn't accept nil as a value, so it would fail
70
+ if val.nil?
71
+ return [] if type == Array || type.is_a?(Array)
72
+ return Set.new if type == Set
73
+ return {} if type == Hash
55
74
  end
56
75
 
57
- converter.coerce(val)
76
+ converter.call(val)
58
77
 
59
- # not the prettiest but some invalid coercion can currently trigger
60
- # errors in Virtus (see coerce_spec.rb:75)
78
+ # Some custom types might fail, so it should be treated as an invalid value
61
79
  rescue
62
80
  Types::InvalidValue.new
63
81
  end
@@ -69,9 +87,8 @@ module Grape
69
87
  @option[:type].is_a?(Hash) ? @option[:type][:value] : @option[:type]
70
88
  end
71
89
 
72
- def requires_coercion?(value)
73
- # JSON types do not require coercion if value is valid
74
- !valid_type?(value) || converter.coercer.respond_to?(:method) && !converter.is_a?(Grape::Validations::Types::Json)
90
+ def validation_exception(attr_name)
91
+ Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:coerce))
75
92
  end
76
93
  end
77
94
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class DefaultValidator < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'grape/validations/validators/multiple_params_base'
2
4
 
3
5
  module Grape
@@ -5,7 +7,7 @@ module Grape
5
7
  class ExactlyOneOfValidator < MultipleParamsBase
6
8
  def validate_params!(params)
7
9
  return if keys_in_common(params).length == 1
8
- raise Grape::Exceptions::Validation, params: all_keys, message: message(:exactly_one)
10
+ raise Grape::Exceptions::Validation.new(params: all_keys, message: message(:exactly_one))
9
11
  end
10
12
  end
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class ExceptValuesValidator < Base
@@ -13,7 +15,7 @@ module Grape
13
15
  return if excepts.nil?
14
16
 
15
17
  param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
16
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:except_values) if param_array.any? { |param| excepts.include?(param) }
18
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:except_values)) if param_array.any? { |param| excepts.include?(param) }
17
19
  end
18
20
  end
19
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class MultipleParamsBase < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'grape/validations/validators/multiple_params_base'
2
4
 
3
5
  module Grape
@@ -6,7 +8,7 @@ module Grape
6
8
  def validate_params!(params)
7
9
  keys = keys_in_common(params)
8
10
  return if keys.length <= 1
9
- raise Grape::Exceptions::Validation, params: keys, message: message(:mutual_exclusion)
11
+ raise Grape::Exceptions::Validation.new(params: keys, message: message(:mutual_exclusion))
10
12
  end
11
13
  end
12
14
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class PresenceValidator < Base
4
6
  def validate_param!(attr_name, params)
5
7
  return if params.respond_to?(:key?) && params.key?(attr_name)
6
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:presence)
8
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:presence))
7
9
  end
8
10
  end
9
11
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class RegexpValidator < Base
4
6
  def validate_param!(attr_name, params)
5
7
  return unless params.respond_to?(:key?) && params.key?(attr_name)
6
8
  return if Array.wrap(params[attr_name]).all? { |param| param.nil? || (param.to_s =~ (options_key?(:value) ? @option[:value] : @option)) }
7
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:regexp)
9
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:regexp))
8
10
  end
9
11
  end
10
12
  end
@@ -1,12 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class SameAsValidator < Base
4
6
  def validate_param!(attr_name, params)
5
7
  confirmation = options_key?(:value) ? @option[:value] : @option
6
8
  return if params[attr_name] == params[confirmation]
7
- raise Grape::Exceptions::Validation,
8
- params: [@scope.full_name(attr_name)],
9
- message: build_message
9
+ raise Grape::Exceptions::Validation.new(
10
+ params: [@scope.full_name(attr_name)],
11
+ message: build_message
12
+ )
10
13
  end
11
14
 
12
15
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class ValuesValidator < Base
@@ -24,17 +26,23 @@ module Grape
24
26
 
25
27
  def validate_param!(attr_name, params)
26
28
  return unless params.is_a?(Hash)
27
- return unless params[attr_name] || required_for_root_scope?
28
29
 
29
- param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
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
30
36
 
31
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: except_message \
37
+ param_array = val.nil? ? [nil] : Array.wrap(val)
38
+
39
+ raise validation_exception(attr_name, except_message) \
32
40
  unless check_excepts(param_array)
33
41
 
34
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:values) \
42
+ raise validation_exception(attr_name, message(:values)) \
35
43
  unless check_values(param_array, attr_name)
36
44
 
37
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:values) \
45
+ raise validation_exception(attr_name, message(:values)) \
38
46
  if @proc && !param_array.all? { |param| @proc.call(param) }
39
47
  end
40
48
 
@@ -66,6 +74,10 @@ module Grape
66
74
  def required_for_root_scope?
67
75
  @required && @scope.root?
68
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
69
81
  end
70
82
  end
71
83
  end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  # The current version of Grape.
3
- VERSION = '1.2.5'.freeze
5
+ VERSION = '1.3.0'
4
6
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations do
@@ -8,7 +10,7 @@ describe Grape::Validations do
8
10
  def validate_param!(attr_name, params)
9
11
  @option = params[:max].to_i if params.key?(:max)
10
12
  return if params[attr_name].length <= @option
11
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long"
13
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
12
14
  end
13
15
  end
14
16
  end
@@ -87,7 +89,7 @@ describe Grape::Validations do
87
89
  module CustomValidationsSpec
88
90
  class WithMessageKey < Grape::Validations::PresenceValidator
89
91
  def validate_param!(attr_name, _params)
90
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: :presence
92
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
91
93
  end
92
94
  end
93
95
  end
@@ -126,7 +128,7 @@ describe Grape::Validations do
126
128
  return unless @option
127
129
  # check if user is admin or not
128
130
  # as an example get a token from request and check if it's admin or not
129
- raise Grape::Exceptions::Validation, params: @attrs, message: 'Can not set Admin only field.' unless request.headers['X-Access-Token'] == 'admin'
131
+ raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
130
132
  end
131
133
  end
132
134
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module DeeplyIncludedOptionsSpec
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Instance do
@@ -21,7 +23,7 @@ describe Grape::API::Instance do
21
23
  { class: 'TrueClass', value: true }.to_s
22
24
  end
23
25
 
24
- it 'sets Boolean as a Virtus::Attribute::Boolean' do
26
+ it 'sets Boolean as a type' do
25
27
  post '/echo?message=true'
26
28
  expect(last_response.status).to eq(201)
27
29
  expect(last_response.body).to eq expected_body
@@ -29,8 +31,8 @@ describe Grape::API::Instance do
29
31
 
30
32
  context 'Params endpoint type' do
31
33
  subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
32
- it 'params type is a Virtus::Attribute::Boolean' do
33
- is_expected.to eq 'Virtus::Attribute::Boolean'
34
+ it 'params type is a boolean' do
35
+ is_expected.to eq 'Grape::API::Boolean'
34
36
  end
35
37
  end
36
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'shared/versioning_examples'
5
+
6
+ describe Grape::API::Instance do
7
+ subject(:an_instance) do
8
+ Class.new(Grape::API::Instance) do
9
+ namespace :some_namespace do
10
+ get 'some_endpoint' do
11
+ 'success'
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:root_api) do
18
+ to_mount = an_instance
19
+ Class.new(Grape::API) do
20
+ mount to_mount
21
+ end
22
+ end
23
+
24
+ def app
25
+ root_api
26
+ end
27
+
28
+ context 'when an instance is mounted on the root' do
29
+ it 'can call the instance endpoint' do
30
+ get '/some_namespace/some_endpoint'
31
+ expect(last_response.body).to eq 'success'
32
+ end
33
+ end
34
+
35
+ context 'when an instance is the root' do
36
+ let(:root_api) do
37
+ to_mount = an_instance
38
+ Class.new(Grape::API::Instance) do
39
+ mount to_mount
40
+ end
41
+ end
42
+
43
+ it 'can call the instance endpoint' do
44
+ get '/some_namespace/some_endpoint'
45
+ expect(last_response.body).to eq 'success'
46
+ end
47
+ end
48
+
49
+ context 'top level setting' do
50
+ it 'does not inherit settings from the superclass (Grape::API::Instance)' do
51
+ expect(an_instance.top_level_setting.parent).to be_nil
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do