grape 1.1.0 → 1.5.3

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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +278 -44
  3. data/LICENSE +1 -1
  4. data/README.md +514 -69
  5. data/UPGRADING.md +424 -17
  6. data/grape.gemspec +13 -2
  7. data/lib/grape.rb +104 -71
  8. data/lib/grape/api.rb +138 -175
  9. data/lib/grape/api/helpers.rb +2 -0
  10. data/lib/grape/api/instance.rb +283 -0
  11. data/lib/grape/config.rb +34 -0
  12. data/lib/grape/content_types.rb +34 -0
  13. data/lib/grape/cookies.rb +2 -0
  14. data/lib/grape/dsl/api.rb +2 -0
  15. data/lib/grape/dsl/callbacks.rb +22 -0
  16. data/lib/grape/dsl/configuration.rb +2 -0
  17. data/lib/grape/dsl/desc.rb +41 -7
  18. data/lib/grape/dsl/headers.rb +2 -0
  19. data/lib/grape/dsl/helpers.rb +5 -2
  20. data/lib/grape/dsl/inside_route.rb +92 -49
  21. data/lib/grape/dsl/logger.rb +2 -0
  22. data/lib/grape/dsl/middleware.rb +9 -0
  23. data/lib/grape/dsl/parameters.rb +25 -14
  24. data/lib/grape/dsl/request_response.rb +4 -2
  25. data/lib/grape/dsl/routing.rb +17 -10
  26. data/lib/grape/dsl/settings.rb +7 -1
  27. data/lib/grape/dsl/validations.rb +24 -4
  28. data/lib/grape/eager_load.rb +20 -0
  29. data/lib/grape/endpoint.rb +59 -35
  30. data/lib/grape/error_formatter.rb +4 -2
  31. data/lib/grape/error_formatter/base.rb +2 -0
  32. data/lib/grape/error_formatter/json.rb +2 -0
  33. data/lib/grape/error_formatter/txt.rb +2 -0
  34. data/lib/grape/error_formatter/xml.rb +2 -0
  35. data/lib/grape/exceptions/base.rb +20 -14
  36. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  37. data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
  38. data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
  39. data/lib/grape/exceptions/invalid_formatter.rb +2 -0
  40. data/lib/grape/exceptions/invalid_message_body.rb +2 -0
  41. data/lib/grape/exceptions/invalid_response.rb +11 -0
  42. data/lib/grape/exceptions/invalid_version_header.rb +2 -0
  43. data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
  44. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
  45. data/lib/grape/exceptions/method_not_allowed.rb +2 -0
  46. data/lib/grape/exceptions/missing_group_type.rb +2 -0
  47. data/lib/grape/exceptions/missing_mime_type.rb +2 -0
  48. data/lib/grape/exceptions/missing_option.rb +2 -0
  49. data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
  50. data/lib/grape/exceptions/unknown_options.rb +2 -0
  51. data/lib/grape/exceptions/unknown_parameter.rb +2 -0
  52. data/lib/grape/exceptions/unknown_validator.rb +2 -0
  53. data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
  54. data/lib/grape/exceptions/validation.rb +4 -2
  55. data/lib/grape/exceptions/validation_array_errors.rb +2 -0
  56. data/lib/grape/exceptions/validation_errors.rb +16 -13
  57. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
  58. data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
  59. data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
  60. data/lib/grape/extensions/hash.rb +2 -0
  61. data/lib/grape/extensions/hashie/mash.rb +2 -0
  62. data/lib/grape/formatter.rb +5 -3
  63. data/lib/grape/formatter/json.rb +2 -0
  64. data/lib/grape/formatter/serializable_hash.rb +2 -0
  65. data/lib/grape/formatter/txt.rb +2 -0
  66. data/lib/grape/formatter/xml.rb +2 -0
  67. data/lib/grape/http/headers.rb +50 -18
  68. data/lib/grape/locale/en.yml +3 -1
  69. data/lib/grape/middleware/auth/base.rb +7 -7
  70. data/lib/grape/middleware/auth/dsl.rb +2 -0
  71. data/lib/grape/middleware/auth/strategies.rb +2 -0
  72. data/lib/grape/middleware/auth/strategy_info.rb +2 -0
  73. data/lib/grape/middleware/base.rb +10 -7
  74. data/lib/grape/middleware/error.rb +21 -16
  75. data/lib/grape/middleware/filter.rb +2 -0
  76. data/lib/grape/middleware/formatter.rb +8 -6
  77. data/lib/grape/middleware/globals.rb +2 -0
  78. data/lib/grape/middleware/helpers.rb +12 -0
  79. data/lib/grape/middleware/stack.rb +13 -3
  80. data/lib/grape/middleware/versioner.rb +2 -0
  81. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
  82. data/lib/grape/middleware/versioner/header.rb +10 -8
  83. data/lib/grape/middleware/versioner/param.rb +3 -1
  84. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
  85. data/lib/grape/middleware/versioner/path.rb +3 -1
  86. data/lib/grape/namespace.rb +14 -2
  87. data/lib/grape/parser.rb +4 -2
  88. data/lib/grape/parser/json.rb +3 -1
  89. data/lib/grape/parser/xml.rb +3 -1
  90. data/lib/grape/path.rb +15 -3
  91. data/lib/grape/presenters/presenter.rb +2 -0
  92. data/lib/grape/request.rb +19 -10
  93. data/lib/grape/router.rb +30 -29
  94. data/lib/grape/router/attribute_translator.rb +41 -8
  95. data/lib/grape/router/pattern.rb +20 -16
  96. data/lib/grape/router/route.rb +14 -28
  97. data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
  98. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
  99. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
  100. data/lib/grape/util/base_inheritable.rb +43 -0
  101. data/lib/grape/util/cache.rb +20 -0
  102. data/lib/grape/util/endpoint_configuration.rb +8 -0
  103. data/lib/grape/util/env.rb +19 -17
  104. data/lib/grape/util/inheritable_setting.rb +2 -0
  105. data/lib/grape/util/inheritable_values.rb +7 -25
  106. data/lib/grape/util/json.rb +2 -0
  107. data/lib/grape/util/lazy_block.rb +27 -0
  108. data/lib/grape/util/lazy_object.rb +43 -0
  109. data/lib/grape/util/lazy_value.rb +98 -0
  110. data/lib/grape/util/registrable.rb +2 -0
  111. data/lib/grape/util/reverse_stackable_values.rb +10 -35
  112. data/lib/grape/util/stackable_values.rb +21 -34
  113. data/lib/grape/util/strict_hash_configuration.rb +2 -0
  114. data/lib/grape/util/xml.rb +2 -0
  115. data/lib/grape/validations.rb +2 -0
  116. data/lib/grape/validations/attributes_iterator.rb +16 -6
  117. data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
  118. data/lib/grape/validations/params_scope.rb +51 -30
  119. data/lib/grape/validations/single_attribute_iterator.rb +24 -0
  120. data/lib/grape/validations/types.rb +13 -38
  121. data/lib/grape/validations/types/array_coercer.rb +65 -0
  122. data/lib/grape/validations/types/build_coercer.rb +47 -49
  123. data/lib/grape/validations/types/custom_type_coercer.rb +29 -51
  124. data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
  125. data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
  126. data/lib/grape/validations/types/file.rb +22 -18
  127. data/lib/grape/validations/types/invalid_value.rb +24 -0
  128. data/lib/grape/validations/types/json.rb +46 -39
  129. data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
  130. data/lib/grape/validations/types/primitive_coercer.rb +67 -0
  131. data/lib/grape/validations/types/set_coercer.rb +40 -0
  132. data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
  133. data/lib/grape/validations/validator_factory.rb +8 -11
  134. data/lib/grape/validations/validators/all_or_none.rb +8 -13
  135. data/lib/grape/validations/validators/allow_blank.rb +3 -1
  136. data/lib/grape/validations/validators/as.rb +5 -4
  137. data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
  138. data/lib/grape/validations/validators/base.rb +20 -16
  139. data/lib/grape/validations/validators/coerce.rb +46 -29
  140. data/lib/grape/validations/validators/default.rb +6 -6
  141. data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
  142. data/lib/grape/validations/validators/except_values.rb +4 -2
  143. data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
  144. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
  145. data/lib/grape/validations/validators/presence.rb +3 -1
  146. data/lib/grape/validations/validators/regexp.rb +4 -2
  147. data/lib/grape/validations/validators/same_as.rb +26 -0
  148. data/lib/grape/validations/validators/values.rb +18 -6
  149. data/lib/grape/version.rb +3 -1
  150. data/spec/grape/api/custom_validations_spec.rb +5 -3
  151. data/spec/grape/api/deeply_included_options_spec.rb +2 -0
  152. data/spec/grape/api/defines_boolean_in_params_spec.rb +39 -0
  153. data/spec/grape/api/inherited_helpers_spec.rb +2 -0
  154. data/spec/grape/api/instance_spec.rb +104 -0
  155. data/spec/grape/api/invalid_format_spec.rb +2 -0
  156. data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
  157. data/spec/grape/api/nested_helpers_spec.rb +2 -0
  158. data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
  159. data/spec/grape/api/parameters_modification_spec.rb +3 -1
  160. data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
  161. data/spec/grape/api/recognize_path_spec.rb +2 -0
  162. data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
  163. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
  164. data/spec/grape/api/routes_with_requirements_spec.rb +61 -0
  165. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
  166. data/spec/grape/api/shared_helpers_spec.rb +2 -0
  167. data/spec/grape/api_remount_spec.rb +473 -0
  168. data/spec/grape/api_spec.rb +565 -12
  169. data/spec/grape/config_spec.rb +19 -0
  170. data/spec/grape/dsl/callbacks_spec.rb +2 -0
  171. data/spec/grape/dsl/configuration_spec.rb +2 -0
  172. data/spec/grape/dsl/desc_spec.rb +42 -16
  173. data/spec/grape/dsl/headers_spec.rb +2 -0
  174. data/spec/grape/dsl/helpers_spec.rb +4 -2
  175. data/spec/grape/dsl/inside_route_spec.rb +184 -33
  176. data/spec/grape/dsl/logger_spec.rb +2 -0
  177. data/spec/grape/dsl/middleware_spec.rb +10 -0
  178. data/spec/grape/dsl/parameters_spec.rb +2 -0
  179. data/spec/grape/dsl/request_response_spec.rb +2 -0
  180. data/spec/grape/dsl/routing_spec.rb +12 -0
  181. data/spec/grape/dsl/settings_spec.rb +2 -0
  182. data/spec/grape/dsl/validations_spec.rb +2 -0
  183. data/spec/grape/endpoint/declared_spec.rb +601 -0
  184. data/spec/grape/endpoint_spec.rb +53 -523
  185. data/spec/grape/entity_spec.rb +9 -1
  186. data/spec/grape/exceptions/base_spec.rb +67 -0
  187. data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
  188. data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
  189. data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
  190. data/spec/grape/exceptions/invalid_response_spec.rb +13 -0
  191. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
  192. data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
  193. data/spec/grape/exceptions/missing_option_spec.rb +2 -0
  194. data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
  195. data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
  196. data/spec/grape/exceptions/validation_errors_spec.rb +8 -4
  197. data/spec/grape/exceptions/validation_spec.rb +3 -1
  198. data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
  199. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
  200. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
  201. data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
  202. data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
  203. data/spec/grape/integration/rack_spec.rb +25 -7
  204. data/spec/grape/loading_spec.rb +2 -0
  205. data/spec/grape/middleware/auth/base_spec.rb +2 -0
  206. data/spec/grape/middleware/auth/dsl_spec.rb +5 -3
  207. data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
  208. data/spec/grape/middleware/base_spec.rb +10 -0
  209. data/spec/grape/middleware/error_spec.rb +3 -1
  210. data/spec/grape/middleware/exception_spec.rb +4 -2
  211. data/spec/grape/middleware/formatter_spec.rb +33 -16
  212. data/spec/grape/middleware/globals_spec.rb +2 -0
  213. data/spec/grape/middleware/stack_spec.rb +12 -0
  214. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
  215. data/spec/grape/middleware/versioner/header_spec.rb +9 -1
  216. data/spec/grape/middleware/versioner/param_spec.rb +3 -1
  217. data/spec/grape/middleware/versioner/path_spec.rb +3 -1
  218. data/spec/grape/middleware/versioner_spec.rb +2 -0
  219. data/spec/grape/named_api_spec.rb +21 -0
  220. data/spec/grape/parser_spec.rb +7 -5
  221. data/spec/grape/path_spec.rb +6 -4
  222. data/spec/grape/presenters/presenter_spec.rb +2 -0
  223. data/spec/grape/request_spec.rb +26 -0
  224. data/spec/grape/util/inheritable_setting_spec.rb +2 -0
  225. data/spec/grape/util/inheritable_values_spec.rb +2 -0
  226. data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
  227. data/spec/grape/util/stackable_values_spec.rb +3 -1
  228. data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
  229. data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
  230. data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
  231. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +41 -0
  232. data/spec/grape/validations/params_scope_spec.rb +213 -9
  233. data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
  234. data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
  235. data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
  236. data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
  237. data/spec/grape/validations/types_spec.rb +9 -36
  238. data/spec/grape/validations/validators/all_or_none_spec.rb +140 -30
  239. data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
  240. data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
  241. data/spec/grape/validations/validators/coerce_spec.rb +476 -135
  242. data/spec/grape/validations/validators/default_spec.rb +172 -0
  243. data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
  244. data/spec/grape/validations/validators/except_values_spec.rb +4 -1
  245. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
  246. data/spec/grape/validations/validators/presence_spec.rb +30 -0
  247. data/spec/grape/validations/validators/regexp_spec.rb +2 -0
  248. data/spec/grape/validations/validators/same_as_spec.rb +65 -0
  249. data/spec/grape/validations/validators/values_spec.rb +30 -5
  250. data/spec/grape/validations_spec.rb +388 -50
  251. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  252. data/spec/integration/multi_json/json_spec.rb +2 -0
  253. data/spec/integration/multi_xml/xml_spec.rb +2 -0
  254. data/spec/shared/versioning_examples.rb +22 -20
  255. data/spec/spec_helper.rb +12 -1
  256. data/spec/support/basic_auth_encode_helpers.rb +2 -0
  257. data/spec/support/chunks.rb +14 -0
  258. data/spec/support/content_type_helpers.rb +2 -0
  259. data/spec/support/eager_load.rb +19 -0
  260. data/spec/support/endpoint_faker.rb +2 -0
  261. data/spec/support/file_streamer.rb +2 -0
  262. data/spec/support/integer_helpers.rb +2 -0
  263. data/spec/support/versioned_helpers.rb +8 -8
  264. metadata +86 -48
  265. data/Appraisals +0 -32
  266. data/Dangerfile +0 -2
  267. data/Gemfile +0 -33
  268. data/Gemfile.lock +0 -231
  269. data/Guardfile +0 -10
  270. data/RELEASING.md +0 -111
  271. data/Rakefile +0 -25
  272. data/benchmark/simple.rb +0 -27
  273. data/benchmark/simple_with_type_coercer.rb +0 -22
  274. data/gemfiles/multi_json.gemfile +0 -35
  275. data/gemfiles/multi_xml.gemfile +0 -35
  276. data/gemfiles/rack_1.5.2.gemfile +0 -35
  277. data/gemfiles/rack_edge.gemfile +0 -35
  278. data/gemfiles/rails_3.gemfile +0 -36
  279. data/gemfiles/rails_4.gemfile +0 -35
  280. data/gemfiles/rails_5.gemfile +0 -35
  281. data/gemfiles/rails_edge.gemfile +0 -35
  282. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
  283. data/lib/grape/util/content_types.rb +0 -26
  284. data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
  285. data/pkg/grape-0.17.0.gem +0 -0
  286. data/pkg/grape-0.19.0.gem +0 -0
@@ -0,0 +1,26 @@
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,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class ValuesValidator < Base
4
- def initialize(attrs, options, required, scope, opts = {})
6
+ def initialize(attrs, options, required, scope, **opts)
5
7
  if options.is_a?(Hash)
6
8
  @excepts = options[:except]
7
9
  @values = options[:value]
@@ -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
data/lib/grape/version.rb CHANGED
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  # The current version of Grape.
3
- VERSION = '1.1.0'.freeze
5
+ VERSION = '1.5.3'
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
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::API::Instance do
6
+ describe 'boolean constant' do
7
+ module DefinesBooleanInstanceSpec
8
+ class API < Grape::API
9
+ params do
10
+ requires :message, type: Boolean
11
+ end
12
+ post :echo do
13
+ { class: params[:message].class.name, value: params[:message] }
14
+ end
15
+ end
16
+ end
17
+
18
+ def app
19
+ DefinesBooleanInstanceSpec::API
20
+ end
21
+
22
+ let(:expected_body) do
23
+ { class: 'TrueClass', value: true }.to_s
24
+ end
25
+
26
+ it 'sets Boolean as a type' do
27
+ post '/echo?message=true'
28
+ expect(last_response.status).to eq(201)
29
+ expect(last_response.body).to eq expected_body
30
+ end
31
+
32
+ context 'Params endpoint type' do
33
+ subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
34
+ it 'params type is a boolean' do
35
+ is_expected.to eq 'Grape::API::Boolean'
36
+ end
37
+ end
38
+ end
39
+ 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,104 @@
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
+
55
+ context 'with multiple moutes' do
56
+ let(:first) do
57
+ Class.new(Grape::API::Instance) do
58
+ namespace(:some_namespace) do
59
+ route :any, '*path' do
60
+ error!('Not found! (1)', 404)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ let(:second) do
66
+ Class.new(Grape::API::Instance) do
67
+ namespace(:another_namespace) do
68
+ route :any, '*path' do
69
+ error!('Not found! (2)', 404)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ let(:root_api) do
75
+ first_instance = first
76
+ second_instance = second
77
+ Class.new(Grape::API) do
78
+ mount first_instance
79
+ mount first_instance
80
+ mount second_instance
81
+ end
82
+ end
83
+
84
+ it 'does not raise a FrozenError on first instance' do
85
+ expect { patch '/some_namespace/anything' }.not_to \
86
+ raise_error
87
+ end
88
+
89
+ it 'responds the correct body at the first instance' do
90
+ patch '/some_namespace/anything'
91
+ expect(last_response.body).to eq 'Not found! (1)'
92
+ end
93
+
94
+ it 'does not raise a FrozenError on second instance' do
95
+ expect { get '/another_namespace/other' }.not_to \
96
+ raise_error
97
+ end
98
+
99
+ it 'responds the correct body at the second instance' do
100
+ get '/another_namespace/foobar'
101
+ expect(last_response.body).to eq 'Not found! (2)'
102
+ end
103
+ end
104
+ 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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -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
@@ -10,7 +12,7 @@ describe Grape::Endpoint do
10
12
  before do
11
13
  subject.namespace :test do
12
14
  params do
13
- optional :foo, default: '-abcdef'
15
+ optional :foo, default: +'-abcdef'
14
16
  end
15
17
  get do
16
18
  params[:foo].slice!(0)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API do
@@ -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
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::Endpoint do
6
+ subject { Class.new(Grape::API) }
7
+
8
+ def app
9
+ subject
10
+ end
11
+
12
+ context 'get' do
13
+ it 'routes to a namespace param with dots' do
14
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
15
+ get '/' do
16
+ params[:ns_with_dots]
17
+ end
18
+ end
19
+
20
+ get '/test.id.with.dots'
21
+ expect(last_response.status).to eq 200
22
+ expect(last_response.body).to eq 'test.id.with.dots'
23
+ end
24
+
25
+ it 'routes to a path with multiple params with dots' do
26
+ subject.get ':id_with_dots/:another_id_with_dots', requirements: { id_with_dots: %r{[^\/]+},
27
+ another_id_with_dots: %r{[^\/]+} } do
28
+ "#{params[:id_with_dots]}/#{params[:another_id_with_dots]}"
29
+ end
30
+
31
+ get '/test.id/test2.id'
32
+ expect(last_response.status).to eq 200
33
+ expect(last_response.body).to eq 'test.id/test2.id'
34
+ end
35
+
36
+ it 'routes to namespace and path params with dots, with overridden requirements' do
37
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
38
+ get ':another_id_with_dots', requirements: { ns_with_dots: %r{[^\/]+},
39
+ another_id_with_dots: %r{[^\/]+} } do
40
+ "#{params[:ns_with_dots]}/#{params[:another_id_with_dots]}"
41
+ end
42
+ end
43
+
44
+ get '/test.id/test2.id'
45
+ expect(last_response.status).to eq 200
46
+ expect(last_response.body).to eq 'test.id/test2.id'
47
+ end
48
+
49
+ it 'routes to namespace and path params with dots, with merged requirements' do
50
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
51
+ get ':another_id_with_dots', requirements: { another_id_with_dots: %r{[^\/]+} } do
52
+ "#{params[:ns_with_dots]}/#{params[:another_id_with_dots]}"
53
+ end
54
+ end
55
+
56
+ get '/test.id/test2.id'
57
+ expect(last_response.status).to eq 200
58
+ expect(last_response.body).to eq 'test.id/test2.id'
59
+ end
60
+ end
61
+ 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
@@ -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,473 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'shared/versioning_examples'
5
+
6
+ describe Grape::API do
7
+ subject(:a_remounted_api) { Class.new(Grape::API) }
8
+ let(:root_api) { Class.new(Grape::API) }
9
+
10
+ def app
11
+ root_api
12
+ end
13
+
14
+ describe 'remounting an API' do
15
+ context 'with a defined route' do
16
+ before do
17
+ a_remounted_api.get '/votes' do
18
+ '10 votes'
19
+ end
20
+ end
21
+
22
+ context 'when mounting one instance' do
23
+ before do
24
+ root_api.mount a_remounted_api
25
+ end
26
+
27
+ it 'can access the endpoint' do
28
+ get '/votes'
29
+ expect(last_response.body).to eql '10 votes'
30
+ end
31
+ end
32
+
33
+ context 'when mounting twice' do
34
+ before do
35
+ root_api.mount a_remounted_api => '/posts'
36
+ root_api.mount a_remounted_api => '/comments'
37
+ end
38
+
39
+ it 'can access the votes in both places' do
40
+ get '/posts/votes'
41
+ expect(last_response.body).to eql '10 votes'
42
+ get '/comments/votes'
43
+ expect(last_response.body).to eql '10 votes'
44
+ end
45
+ end
46
+
47
+ context 'when mounting on namespace' do
48
+ before do
49
+ stub_const('StaticRefToAPI', a_remounted_api)
50
+ root_api.namespace 'posts' do
51
+ mount StaticRefToAPI
52
+ end
53
+
54
+ root_api.namespace 'comments' do
55
+ mount StaticRefToAPI
56
+ end
57
+ end
58
+
59
+ it 'can access the votes in both places' do
60
+ get '/posts/votes'
61
+ expect(last_response.body).to eql '10 votes'
62
+ get '/comments/votes'
63
+ expect(last_response.body).to eql '10 votes'
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'with dynamic configuration' do
69
+ context 'when mounting an endpoint conditional on a configuration' do
70
+ subject(:a_remounted_api) do
71
+ Class.new(Grape::API) do
72
+ get 'always' do
73
+ 'success'
74
+ end
75
+
76
+ given configuration[:mount_sometimes] do
77
+ get 'sometimes' do
78
+ 'sometimes'
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ it 'mounts the endpoints only when configured to do so' do
85
+ root_api.mount({ a_remounted_api => 'with_conditional' }, with: { mount_sometimes: true })
86
+ root_api.mount({ a_remounted_api => 'without_conditional' }, with: { mount_sometimes: false })
87
+
88
+ get '/with_conditional/always'
89
+ expect(last_response.body).to eq 'success'
90
+
91
+ get '/with_conditional/sometimes'
92
+ expect(last_response.body).to eq 'sometimes'
93
+
94
+ get '/without_conditional/always'
95
+ expect(last_response.body).to eq 'success'
96
+
97
+ get '/without_conditional/sometimes'
98
+ expect(last_response.status).to eq 404
99
+ end
100
+ end
101
+
102
+ context 'when using an expression derived from a configuration' do
103
+ subject(:a_remounted_api) do
104
+ Class.new(Grape::API) do
105
+ get(mounted { "api_name_#{configuration[:api_name]}" }) do
106
+ 'success'
107
+ end
108
+ end
109
+ end
110
+
111
+ before do
112
+ root_api.mount a_remounted_api, with: {
113
+ api_name: 'a_name'
114
+ }
115
+ end
116
+
117
+ it 'mounts the endpoint with the name' do
118
+ get 'api_name_a_name'
119
+ expect(last_response.body).to eq 'success'
120
+ end
121
+
122
+ it 'does not mount the endpoint with a null name' do
123
+ get 'api_name_'
124
+ expect(last_response.body).not_to eq 'success'
125
+ end
126
+
127
+ context 'when the expression lives in a namespace' do
128
+ subject(:a_remounted_api) do
129
+ Class.new(Grape::API) do
130
+ namespace :base do
131
+ get(mounted { "api_name_#{configuration[:api_name]}" }) do
132
+ 'success'
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ it 'mounts the endpoint with the name' do
139
+ get 'base/api_name_a_name'
140
+ expect(last_response.body).to eq 'success'
141
+ end
142
+
143
+ it 'does not mount the endpoint with a null name' do
144
+ get 'base/api_name_'
145
+ expect(last_response.body).not_to eq 'success'
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'when executing a standard block within a `mounted` block with all dynamic params' do
151
+ subject(:a_remounted_api) do
152
+ Class.new(Grape::API) do
153
+ mounted do
154
+ desc configuration[:description] do
155
+ headers configuration[:headers]
156
+ end
157
+ get configuration[:endpoint] do
158
+ configuration[:response]
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ let(:api_endpoint) { 'custom_endpoint' }
165
+ let(:api_response) { 'custom response' }
166
+ let(:endpoint_description) { 'this is a custom API' }
167
+ let(:headers) do
168
+ {
169
+ 'XAuthToken' => {
170
+ 'description' => 'Validates your identity',
171
+ 'required' => true
172
+ }
173
+ }
174
+ end
175
+
176
+ it 'mounts the API and obtains the description and headers definition' do
177
+ root_api.mount a_remounted_api, with: {
178
+ description: endpoint_description,
179
+ headers: headers,
180
+ endpoint: api_endpoint,
181
+ response: api_response
182
+ }
183
+ get api_endpoint
184
+ expect(last_response.body).to eq api_response
185
+ expect(a_remounted_api.instances.last.endpoints.first.options[:route_options][:description])
186
+ .to eq endpoint_description
187
+ expect(a_remounted_api.instances.last.endpoints.first.options[:route_options][:headers])
188
+ .to eq headers
189
+ end
190
+ end
191
+
192
+ context 'when executing a custom block on mount' do
193
+ subject(:a_remounted_api) do
194
+ Class.new(Grape::API) do
195
+ get 'always' do
196
+ 'success'
197
+ end
198
+
199
+ mounted do
200
+ configuration[:endpoints].each do |endpoint_name, endpoint_response|
201
+ get endpoint_name do
202
+ endpoint_response
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ it 'mounts the endpoints only when configured to do so' do
210
+ root_api.mount a_remounted_api, with: { endpoints: { 'api_name' => 'api_response' } }
211
+ get 'api_name'
212
+ expect(last_response.body).to eq 'api_response'
213
+ end
214
+ end
215
+
216
+ context 'when the configuration is part of the arguments of a method' do
217
+ subject(:a_remounted_api) do
218
+ Class.new(Grape::API) do
219
+ get configuration[:endpoint_name] do
220
+ 'success'
221
+ end
222
+ end
223
+ end
224
+
225
+ it 'mounts the endpoint in the location it is configured' do
226
+ root_api.mount a_remounted_api, with: { endpoint_name: 'some_location' }
227
+ get '/some_location'
228
+ expect(last_response.body).to eq 'success'
229
+
230
+ get '/different_location'
231
+ expect(last_response.status).to eq 404
232
+
233
+ root_api.mount a_remounted_api, with: { endpoint_name: 'new_location' }
234
+ get '/new_location'
235
+ expect(last_response.body).to eq 'success'
236
+ end
237
+
238
+ context 'when the configuration is the value in a key-arg pair' do
239
+ subject(:a_remounted_api) do
240
+ Class.new(Grape::API) do
241
+ version 'v1', using: :param, parameter: configuration[:version_param]
242
+ get 'endpoint' do
243
+ 'version 1'
244
+ end
245
+
246
+ version 'v2', using: :param, parameter: configuration[:version_param]
247
+ get 'endpoint' do
248
+ 'version 2'
249
+ end
250
+ end
251
+ end
252
+
253
+ it 'takes the param from the configuration' do
254
+ root_api.mount a_remounted_api, with: { version_param: 'param_name' }
255
+
256
+ get '/endpoint?param_name=v1'
257
+ expect(last_response.body).to eq 'version 1'
258
+
259
+ get '/endpoint?param_name=v2'
260
+ expect(last_response.body).to eq 'version 2'
261
+
262
+ get '/endpoint?wrong_param_name=v2'
263
+ expect(last_response.body).to eq 'version 1'
264
+ end
265
+ end
266
+ end
267
+
268
+ context 'on the DescSCope' do
269
+ subject(:a_remounted_api) do
270
+ Class.new(Grape::API) do
271
+ desc 'The description of this' do
272
+ tags ['not_configurable_tag', configuration[:a_configurable_tag]]
273
+ end
274
+ get 'location' do
275
+ 'success'
276
+ end
277
+ end
278
+ end
279
+
280
+ it 'mounts the endpoint with the appropiate tags' do
281
+ root_api.mount({ a_remounted_api => 'integer' }, with: { a_configurable_tag: 'a configured tag' })
282
+ end
283
+ end
284
+
285
+ context 'on the ParamScope' do
286
+ subject(:a_remounted_api) do
287
+ Class.new(Grape::API) do
288
+ params do
289
+ requires configuration[:required_param], type: configuration[:required_type]
290
+ end
291
+
292
+ get 'location' do
293
+ 'success'
294
+ end
295
+ end
296
+ end
297
+
298
+ it 'mounts the endpoint in the location it is configured' do
299
+ root_api.mount({ a_remounted_api => 'string' }, with: { required_param: 'param_key', required_type: String })
300
+ root_api.mount({ a_remounted_api => 'integer' }, with: { required_param: 'param_integer', required_type: Integer })
301
+
302
+ get '/string/location', param_key: 'a'
303
+ expect(last_response.body).to eq 'success'
304
+
305
+ get '/string/location', param_integer: 1
306
+ expect(last_response.status).to eq 400
307
+
308
+ get '/integer/location', param_integer: 1
309
+ expect(last_response.body).to eq 'success'
310
+
311
+ get '/integer/location', param_integer: 'a'
312
+ expect(last_response.status).to eq 400
313
+ end
314
+
315
+ context 'on dynamic checks' do
316
+ subject(:a_remounted_api) do
317
+ Class.new(Grape::API) do
318
+ params do
319
+ optional :restricted_values, values: -> { [configuration[:allowed_value], 'always'] }
320
+ end
321
+
322
+ get 'location' do
323
+ 'success'
324
+ end
325
+ end
326
+ end
327
+
328
+ it 'can read the configuration on lambdas' do
329
+ root_api.mount a_remounted_api, with: { allowed_value: 'sometimes' }
330
+ get '/location', restricted_values: 'always'
331
+ expect(last_response.body).to eq 'success'
332
+ get '/location', restricted_values: 'sometimes'
333
+ expect(last_response.body).to eq 'success'
334
+ get '/location', restricted_values: 'never'
335
+ expect(last_response.status).to eq 400
336
+ end
337
+ end
338
+ end
339
+
340
+ context 'when the configuration is read within a namespace' do
341
+ before do
342
+ a_remounted_api.namespace 'api' do
343
+ params do
344
+ requires configuration[:required_param]
345
+ end
346
+ get "/#{configuration[:path]}" do
347
+ '10 votes'
348
+ end
349
+ end
350
+ root_api.mount a_remounted_api, with: { path: 'votes', required_param: 'param_key' }
351
+ root_api.mount a_remounted_api, with: { path: 'scores', required_param: 'param_key' }
352
+ end
353
+
354
+ it 'will use the dynamic configuration on all routes' do
355
+ get 'api/votes', param_key: 'a'
356
+ expect(last_response.body).to eql '10 votes'
357
+ get 'api/scores', param_key: 'a'
358
+ expect(last_response.body).to eql '10 votes'
359
+ get 'api/votes'
360
+ expect(last_response.status).to eq 400
361
+ end
362
+ end
363
+
364
+ context 'a very complex configuration example' do
365
+ before do
366
+ top_level_api = Class.new(Grape::API) do
367
+ remounted_api = Class.new(Grape::API) do
368
+ get configuration[:endpoint_name] do
369
+ configuration[:response]
370
+ end
371
+ end
372
+
373
+ expression_namespace = mounted { configuration[:namespace].to_s * 2 }
374
+ given(mounted { configuration[:should_mount_expressed] != false }) do
375
+ namespace expression_namespace do
376
+ mount remounted_api, with: { endpoint_name: configuration[:endpoint_name], response: configuration[:endpoint_response] }
377
+ end
378
+ end
379
+ end
380
+ root_api.mount top_level_api, with: configuration_options
381
+ end
382
+
383
+ context 'when the namespace should be mounted' do
384
+ let(:configuration_options) do
385
+ {
386
+ should_mount_expressed: true,
387
+ namespace: 'bang',
388
+ endpoint_name: 'james',
389
+ endpoint_response: 'bond'
390
+ }
391
+ end
392
+
393
+ it 'gets a response' do
394
+ get 'bangbang/james'
395
+ expect(last_response.body).to eq 'bond'
396
+ end
397
+ end
398
+
399
+ context 'when should be mounted is nil' do
400
+ let(:configuration_options) do
401
+ {
402
+ should_mount_expressed: nil,
403
+ namespace: 'bang',
404
+ endpoint_name: 'james',
405
+ endpoint_response: 'bond'
406
+ }
407
+ end
408
+
409
+ it 'gets a response' do
410
+ get 'bangbang/james'
411
+ expect(last_response.body).to eq 'bond'
412
+ end
413
+ end
414
+
415
+ context 'when it should not be mounted' do
416
+ let(:configuration_options) do
417
+ {
418
+ should_mount_expressed: false,
419
+ namespace: 'bang',
420
+ endpoint_name: 'james',
421
+ endpoint_response: 'bond'
422
+ }
423
+ end
424
+
425
+ it 'gets a response' do
426
+ get 'bangbang/james'
427
+ expect(last_response.body).not_to eq 'bond'
428
+ end
429
+ end
430
+ end
431
+
432
+ context 'when the configuration is read in a helper' do
433
+ subject(:a_remounted_api) do
434
+ Class.new(Grape::API) do
435
+ helpers do
436
+ def printed_response
437
+ configuration[:some_value]
438
+ end
439
+ end
440
+
441
+ get 'location' do
442
+ printed_response
443
+ end
444
+ end
445
+ end
446
+
447
+ it 'will use the dynamic configuration on all routes' do
448
+ root_api.mount(a_remounted_api, with: { some_value: 'response value' })
449
+
450
+ get '/location'
451
+ expect(last_response.body).to eq 'response value'
452
+ end
453
+ end
454
+
455
+ context 'when the configuration is read within the response block' do
456
+ subject(:a_remounted_api) do
457
+ Class.new(Grape::API) do
458
+ get 'location' do
459
+ configuration[:some_value]
460
+ end
461
+ end
462
+ end
463
+
464
+ it 'will use the dynamic configuration on all routes' do
465
+ root_api.mount(a_remounted_api, with: { some_value: 'response value' })
466
+
467
+ get '/location'
468
+ expect(last_response.body).to eq 'response value'
469
+ end
470
+ end
471
+ end
472
+ end
473
+ end