actionpack 5.0.7.2 → 5.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (128) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +189 -1002
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/abstract_controller.rb +3 -3
  6. data/lib/abstract_controller/base.rb +10 -12
  7. data/lib/abstract_controller/caching.rb +6 -3
  8. data/lib/abstract_controller/caching/fragments.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +2 -43
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/helpers.rb +19 -19
  12. data/lib/abstract_controller/rendering.rb +9 -11
  13. data/lib/abstract_controller/translation.rb +3 -3
  14. data/lib/action_controller.rb +15 -13
  15. data/lib/action_controller/api.rb +3 -3
  16. data/lib/action_controller/base.rb +7 -12
  17. data/lib/action_controller/caching.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +2 -2
  19. data/lib/action_controller/metal.rb +34 -43
  20. data/lib/action_controller/metal/conditional_get.rb +10 -9
  21. data/lib/action_controller/metal/data_streaming.rb +8 -9
  22. data/lib/action_controller/metal/etag_with_flash.rb +16 -0
  23. data/lib/action_controller/metal/etag_with_template_digest.rb +15 -15
  24. data/lib/action_controller/metal/exceptions.rb +4 -14
  25. data/lib/action_controller/metal/flash.rb +1 -1
  26. data/lib/action_controller/metal/force_ssl.rb +6 -6
  27. data/lib/action_controller/metal/head.rb +13 -19
  28. data/lib/action_controller/metal/helpers.rb +6 -6
  29. data/lib/action_controller/metal/http_authentication.rb +22 -23
  30. data/lib/action_controller/metal/implicit_render.rb +2 -5
  31. data/lib/action_controller/metal/instrumentation.rb +14 -14
  32. data/lib/action_controller/metal/live.rb +15 -16
  33. data/lib/action_controller/metal/mime_responds.rb +3 -3
  34. data/lib/action_controller/metal/parameter_encoding.rb +49 -0
  35. data/lib/action_controller/metal/params_wrapper.rb +32 -32
  36. data/lib/action_controller/metal/redirecting.rb +8 -24
  37. data/lib/action_controller/metal/renderers.rb +2 -3
  38. data/lib/action_controller/metal/rendering.rb +50 -60
  39. data/lib/action_controller/metal/request_forgery_protection.rb +51 -49
  40. data/lib/action_controller/metal/rescue.rb +1 -1
  41. data/lib/action_controller/metal/streaming.rb +4 -4
  42. data/lib/action_controller/metal/strong_parameters.rb +117 -250
  43. data/lib/action_controller/metal/testing.rb +1 -1
  44. data/lib/action_controller/metal/url_for.rb +4 -4
  45. data/lib/action_controller/railtie.rb +9 -13
  46. data/lib/action_controller/renderer.rb +17 -16
  47. data/lib/action_controller/test_case.rb +75 -148
  48. data/lib/action_dispatch.rb +20 -19
  49. data/lib/action_dispatch/http/cache.rb +9 -10
  50. data/lib/action_dispatch/http/filter_parameters.rb +8 -8
  51. data/lib/action_dispatch/http/filter_redirect.rb +2 -4
  52. data/lib/action_dispatch/http/headers.rb +10 -10
  53. data/lib/action_dispatch/http/mime_negotiation.rb +17 -22
  54. data/lib/action_dispatch/http/mime_type.rb +27 -52
  55. data/lib/action_dispatch/http/parameter_filter.rb +8 -6
  56. data/lib/action_dispatch/http/parameters.rb +40 -17
  57. data/lib/action_dispatch/http/request.rb +38 -34
  58. data/lib/action_dispatch/http/response.rb +16 -16
  59. data/lib/action_dispatch/http/upload.rb +6 -10
  60. data/lib/action_dispatch/http/url.rb +48 -74
  61. data/lib/action_dispatch/journey.rb +5 -5
  62. data/lib/action_dispatch/journey/formatter.rb +8 -4
  63. data/lib/action_dispatch/journey/gtg/builder.rb +5 -5
  64. data/lib/action_dispatch/journey/gtg/simulator.rb +1 -1
  65. data/lib/action_dispatch/journey/gtg/transition_table.rb +15 -15
  66. data/lib/action_dispatch/journey/nfa/builder.rb +3 -3
  67. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  68. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  69. data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -2
  70. data/lib/action_dispatch/journey/nodes/node.rb +5 -5
  71. data/lib/action_dispatch/journey/parser.rb +23 -24
  72. data/lib/action_dispatch/journey/parser.y +3 -2
  73. data/lib/action_dispatch/journey/parser_extras.rb +2 -2
  74. data/lib/action_dispatch/journey/path/pattern.rb +10 -3
  75. data/lib/action_dispatch/journey/route.rb +19 -12
  76. data/lib/action_dispatch/journey/router.rb +19 -12
  77. data/lib/action_dispatch/journey/router/utils.rb +9 -9
  78. data/lib/action_dispatch/journey/scanner.rb +17 -15
  79. data/lib/action_dispatch/journey/visitors.rb +23 -23
  80. data/lib/action_dispatch/middleware/callbacks.rb +0 -12
  81. data/lib/action_dispatch/middleware/cookies.rb +39 -39
  82. data/lib/action_dispatch/middleware/debug_exceptions.rb +126 -112
  83. data/lib/action_dispatch/middleware/debug_locks.rb +8 -8
  84. data/lib/action_dispatch/middleware/exception_wrapper.rb +55 -55
  85. data/lib/action_dispatch/middleware/executor.rb +1 -1
  86. data/lib/action_dispatch/middleware/flash.rb +17 -16
  87. data/lib/action_dispatch/middleware/public_exceptions.rb +20 -20
  88. data/lib/action_dispatch/middleware/reloader.rb +3 -47
  89. data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
  90. data/lib/action_dispatch/middleware/request_id.rb +6 -5
  91. data/lib/action_dispatch/middleware/session/abstract_store.rb +14 -26
  92. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  93. data/lib/action_dispatch/middleware/session/cookie_store.rb +35 -35
  94. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
  95. data/lib/action_dispatch/middleware/show_exceptions.rb +19 -19
  96. data/lib/action_dispatch/middleware/ssl.rb +9 -27
  97. data/lib/action_dispatch/middleware/stack.rb +7 -26
  98. data/lib/action_dispatch/middleware/static.rb +13 -24
  99. data/lib/action_dispatch/railtie.rb +9 -11
  100. data/lib/action_dispatch/request/session.rb +22 -22
  101. data/lib/action_dispatch/request/utils.rb +11 -2
  102. data/lib/action_dispatch/routing.rb +8 -6
  103. data/lib/action_dispatch/routing/inspector.rb +37 -37
  104. data/lib/action_dispatch/routing/mapper.rb +296 -203
  105. data/lib/action_dispatch/routing/polymorphic_routes.rb +160 -134
  106. data/lib/action_dispatch/routing/redirection.rb +27 -22
  107. data/lib/action_dispatch/routing/route_set.rb +206 -92
  108. data/lib/action_dispatch/routing/routes_proxy.rb +2 -2
  109. data/lib/action_dispatch/routing/url_for.rb +14 -12
  110. data/lib/action_dispatch/system_test_case.rb +119 -0
  111. data/lib/action_dispatch/system_testing/browser.rb +28 -0
  112. data/lib/action_dispatch/system_testing/driver.rb +18 -0
  113. data/lib/action_dispatch/system_testing/server.rb +32 -0
  114. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +61 -0
  115. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +20 -0
  116. data/lib/action_dispatch/testing/assertion_response.rb +6 -6
  117. data/lib/action_dispatch/testing/assertions.rb +4 -4
  118. data/lib/action_dispatch/testing/assertions/response.rb +8 -3
  119. data/lib/action_dispatch/testing/assertions/routing.rb +11 -11
  120. data/lib/action_dispatch/testing/integration.rb +47 -138
  121. data/lib/action_dispatch/testing/test_process.rb +2 -2
  122. data/lib/action_dispatch/testing/test_request.rb +16 -16
  123. data/lib/action_dispatch/testing/test_response.rb +1 -1
  124. data/lib/action_pack.rb +2 -2
  125. data/lib/action_pack/gem_version.rb +3 -3
  126. data/lib/action_pack/version.rb +1 -1
  127. metadata +20 -12
  128. data/lib/action_dispatch/middleware/params_parser.rb +0 -46
@@ -4,7 +4,7 @@ module ActionDispatch
4
4
  # given an Active Record model instance. They are to be used in combination with
5
5
  # ActionController::Resources.
6
6
  #
7
- # These methods are useful when you want to generate correct URL or path to a RESTful
7
+ # These methods are useful when you want to generate the correct URL or path to a RESTful
8
8
  # resource without having to know the exact type of the record in question.
9
9
  #
10
10
  # Nested resources and/or namespaces are also supported, as illustrated in the example:
@@ -79,7 +79,7 @@ module ActionDispatch
79
79
  # polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
80
80
  # # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
81
81
  #
82
- # For all of these options, see the documentation for <tt>url_for</tt>.
82
+ # For all of these options, see the documentation for {url_for}[rdoc-ref:ActionDispatch::Routing::UrlFor].
83
83
  #
84
84
  # ==== Functionality
85
85
  #
@@ -103,6 +103,10 @@ module ActionDispatch
103
103
  return polymorphic_url record, options
104
104
  end
105
105
 
106
+ if mapping = polymorphic_mapping(record_or_hash_or_array)
107
+ return mapping.call(self, [record_or_hash_or_array, options])
108
+ end
109
+
106
110
  opts = options.dup
107
111
  action = opts.delete :action
108
112
  type = opts.delete(:routing_type) || :url
@@ -123,6 +127,10 @@ module ActionDispatch
123
127
  return polymorphic_path record, options
124
128
  end
125
129
 
130
+ if mapping = polymorphic_mapping(record_or_hash_or_array)
131
+ return mapping.call(self, [record_or_hash_or_array, options], only_path: true)
132
+ end
133
+
126
134
  opts = options.dup
127
135
  action = opts.delete :action
128
136
  type = :path
@@ -134,7 +142,6 @@ module ActionDispatch
134
142
  opts
135
143
  end
136
144
 
137
-
138
145
  %w(edit new).each do |action|
139
146
  module_eval <<-EOT, __FILE__, __LINE__ + 1
140
147
  def #{action}_polymorphic_url(record_or_hash, options = {})
@@ -149,176 +156,195 @@ module ActionDispatch
149
156
 
150
157
  private
151
158
 
152
- def polymorphic_url_for_action(action, record_or_hash, options)
153
- polymorphic_url(record_or_hash, options.merge(:action => action))
154
- end
155
-
156
- def polymorphic_path_for_action(action, record_or_hash, options)
157
- polymorphic_path(record_or_hash, options.merge(:action => action))
158
- end
159
-
160
- class HelperMethodBuilder # :nodoc:
161
- CACHE = { 'path' => {}, 'url' => {} }
162
-
163
- def self.get(action, type)
164
- type = type.to_s
165
- CACHE[type].fetch(action) { build action, type }
159
+ def polymorphic_url_for_action(action, record_or_hash, options)
160
+ polymorphic_url(record_or_hash, options.merge(action: action))
166
161
  end
167
162
 
168
- def self.url; CACHE['url'.freeze][nil]; end
169
- def self.path; CACHE['path'.freeze][nil]; end
163
+ def polymorphic_path_for_action(action, record_or_hash, options)
164
+ polymorphic_path(record_or_hash, options.merge(action: action))
165
+ end
170
166
 
171
- def self.build(action, type)
172
- prefix = action ? "#{action}_" : ""
173
- suffix = type
174
- if action.to_s == 'new'
175
- HelperMethodBuilder.singular prefix, suffix
167
+ def polymorphic_mapping(record)
168
+ if record.respond_to?(:to_model)
169
+ _routes.polymorphic_mappings[record.to_model.model_name.name]
176
170
  else
177
- HelperMethodBuilder.plural prefix, suffix
171
+ _routes.polymorphic_mappings[record.class.name]
178
172
  end
179
173
  end
180
174
 
181
- def self.singular(prefix, suffix)
182
- new(->(name) { name.singular_route_key }, prefix, suffix)
183
- end
175
+ class HelperMethodBuilder # :nodoc:
176
+ CACHE = { "path" => {}, "url" => {} }
184
177
 
185
- def self.plural(prefix, suffix)
186
- new(->(name) { name.route_key }, prefix, suffix)
187
- end
178
+ def self.get(action, type)
179
+ type = type.to_s
180
+ CACHE[type].fetch(action) { build action, type }
181
+ end
188
182
 
189
- def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
190
- builder = get action, type
183
+ def self.url; CACHE["url".freeze][nil]; end
184
+ def self.path; CACHE["path".freeze][nil]; end
191
185
 
192
- case record_or_hash_or_array
193
- when Array
194
- record_or_hash_or_array = record_or_hash_or_array.compact
195
- if record_or_hash_or_array.empty?
196
- raise ArgumentError, "Nil location provided. Can't build URI."
197
- end
198
- if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
199
- recipient = record_or_hash_or_array.shift
186
+ def self.build(action, type)
187
+ prefix = action ? "#{action}_" : ""
188
+ suffix = type
189
+ if action.to_s == "new"
190
+ HelperMethodBuilder.singular prefix, suffix
191
+ else
192
+ HelperMethodBuilder.plural prefix, suffix
200
193
  end
201
-
202
- method, args = builder.handle_list record_or_hash_or_array
203
- when String, Symbol
204
- method, args = builder.handle_string record_or_hash_or_array
205
- when Class
206
- method, args = builder.handle_class record_or_hash_or_array
207
-
208
- when nil
209
- raise ArgumentError, "Nil location provided. Can't build URI."
210
- else
211
- method, args = builder.handle_model record_or_hash_or_array
212
194
  end
213
195
 
196
+ def self.singular(prefix, suffix)
197
+ new(->(name) { name.singular_route_key }, prefix, suffix)
198
+ end
214
199
 
215
- if options.empty?
216
- recipient.send(method, *args)
217
- else
218
- recipient.send(method, *args, options)
200
+ def self.plural(prefix, suffix)
201
+ new(->(name) { name.route_key }, prefix, suffix)
219
202
  end
220
- end
221
203
 
222
- attr_reader :suffix, :prefix
204
+ def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
205
+ builder = get action, type
206
+
207
+ case record_or_hash_or_array
208
+ when Array
209
+ record_or_hash_or_array = record_or_hash_or_array.compact
210
+ if record_or_hash_or_array.empty?
211
+ raise ArgumentError, "Nil location provided. Can't build URI."
212
+ end
213
+ if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
214
+ recipient = record_or_hash_or_array.shift
215
+ end
216
+
217
+ method, args = builder.handle_list record_or_hash_or_array
218
+ when String, Symbol
219
+ method, args = builder.handle_string record_or_hash_or_array
220
+ when Class
221
+ method, args = builder.handle_class record_or_hash_or_array
223
222
 
224
- def initialize(key_strategy, prefix, suffix)
225
- @key_strategy = key_strategy
226
- @prefix = prefix
227
- @suffix = suffix
228
- end
223
+ when nil
224
+ raise ArgumentError, "Nil location provided. Can't build URI."
225
+ else
226
+ method, args = builder.handle_model record_or_hash_or_array
227
+ end
229
228
 
230
- def handle_string(record)
231
- [get_method_for_string(record), []]
232
- end
229
+ if options.empty?
230
+ recipient.send(method, *args)
231
+ else
232
+ recipient.send(method, *args, options)
233
+ end
234
+ end
233
235
 
234
- def handle_string_call(target, str)
235
- target.send get_method_for_string str
236
- end
236
+ attr_reader :suffix, :prefix
237
237
 
238
- def handle_class(klass)
239
- [get_method_for_class(klass), []]
240
- end
238
+ def initialize(key_strategy, prefix, suffix)
239
+ @key_strategy = key_strategy
240
+ @prefix = prefix
241
+ @suffix = suffix
242
+ end
241
243
 
242
- def handle_class_call(target, klass)
243
- target.send get_method_for_class klass
244
- end
244
+ def handle_string(record)
245
+ [get_method_for_string(record), []]
246
+ end
245
247
 
246
- def handle_model(record)
247
- args = []
248
+ def handle_string_call(target, str)
249
+ target.send get_method_for_string str
250
+ end
248
251
 
249
- model = record.to_model
250
- named_route = if model.persisted?
251
- args << model
252
- get_method_for_string model.model_name.singular_route_key
253
- else
254
- get_method_for_class model
255
- end
252
+ def handle_class(klass)
253
+ [get_method_for_class(klass), []]
254
+ end
256
255
 
257
- [named_route, args]
258
- end
256
+ def handle_class_call(target, klass)
257
+ target.send get_method_for_class klass
258
+ end
259
259
 
260
- def handle_model_call(target, model)
261
- method, args = handle_model model
262
- target.send(method, *args)
263
- end
260
+ def handle_model(record)
261
+ args = []
264
262
 
265
- def handle_list(list)
266
- record_list = list.dup
267
- record = record_list.pop
263
+ model = record.to_model
264
+ named_route = if model.persisted?
265
+ args << model
266
+ get_method_for_string model.model_name.singular_route_key
267
+ else
268
+ get_method_for_class model
269
+ end
268
270
 
269
- args = []
271
+ [named_route, args]
272
+ end
270
273
 
271
- route = record_list.map { |parent|
272
- case parent
273
- when Symbol, String
274
- parent.to_s
275
- when Class
276
- args << parent
277
- parent.model_name.singular_route_key
274
+ def handle_model_call(target, record)
275
+ if mapping = polymorphic_mapping(target, record)
276
+ mapping.call(target, [record], only_path: suffix == "path")
278
277
  else
279
- args << parent.to_model
280
- parent.to_model.model_name.singular_route_key
278
+ method, args = handle_model(record)
279
+ target.send(method, *args)
281
280
  end
282
- }
283
-
284
- route <<
285
- case record
286
- when Symbol, String
287
- record.to_s
288
- when Class
289
- @key_strategy.call record.model_name
290
- else
291
- model = record.to_model
292
- if model.persisted?
293
- args << model
294
- model.model_name.singular_route_key
281
+ end
282
+
283
+ def handle_list(list)
284
+ record_list = list.dup
285
+ record = record_list.pop
286
+
287
+ args = []
288
+
289
+ route = record_list.map { |parent|
290
+ case parent
291
+ when Symbol, String
292
+ parent.to_s
293
+ when Class
294
+ args << parent
295
+ parent.model_name.singular_route_key
296
+ else
297
+ args << parent.to_model
298
+ parent.to_model.model_name.singular_route_key
299
+ end
300
+ }
301
+
302
+ route <<
303
+ case record
304
+ when Symbol, String
305
+ record.to_s
306
+ when Class
307
+ @key_strategy.call record.model_name
295
308
  else
296
- @key_strategy.call model.model_name
309
+ model = record.to_model
310
+ if model.persisted?
311
+ args << model
312
+ model.model_name.singular_route_key
313
+ else
314
+ @key_strategy.call model.model_name
315
+ end
297
316
  end
298
- end
299
317
 
300
- route << suffix
318
+ route << suffix
301
319
 
302
- named_route = prefix + route.join("_")
303
- [named_route, args]
304
- end
320
+ named_route = prefix + route.join("_")
321
+ [named_route, args]
322
+ end
305
323
 
306
- private
324
+ private
307
325
 
308
- def get_method_for_class(klass)
309
- name = @key_strategy.call klass.model_name
310
- get_method_for_string name
311
- end
326
+ def polymorphic_mapping(target, record)
327
+ if record.respond_to?(:to_model)
328
+ target._routes.polymorphic_mappings[record.to_model.model_name.name]
329
+ else
330
+ target._routes.polymorphic_mappings[record.class.name]
331
+ end
332
+ end
312
333
 
313
- def get_method_for_string(str)
314
- "#{prefix}#{str}_#{suffix}"
315
- end
334
+ def get_method_for_class(klass)
335
+ name = @key_strategy.call klass.model_name
336
+ get_method_for_string name
337
+ end
316
338
 
317
- [nil, 'new', 'edit'].each do |action|
318
- CACHE['url'][action] = build action, 'url'
319
- CACHE['path'][action] = build action, 'path'
339
+ def get_method_for_string(str)
340
+ "#{prefix}#{str}_#{suffix}"
341
+ end
342
+
343
+ [nil, "new", "edit"].each do |action|
344
+ CACHE["url"][action] = build action, "url"
345
+ CACHE["path"][action] = build action, "path"
346
+ end
320
347
  end
321
- end
322
348
  end
323
349
  end
324
350
  end
@@ -1,9 +1,9 @@
1
- require 'action_dispatch/http/request'
2
- require 'active_support/core_ext/uri'
3
- require 'active_support/core_ext/array/extract_options'
4
- require 'rack/utils'
5
- require 'action_controller/metal/exceptions'
6
- require 'action_dispatch/routing/endpoint'
1
+ require "action_dispatch/http/request"
2
+ require "active_support/core_ext/uri"
3
+ require "active_support/core_ext/array/extract_options"
4
+ require "rack/utils"
5
+ require "action_controller/metal/exceptions"
6
+ require "action_dispatch/routing/endpoint"
7
7
 
8
8
  module ActionDispatch
9
9
  module Routing
@@ -36,14 +36,12 @@ module ActionDispatch
36
36
  uri.host ||= req.host
37
37
  uri.port ||= req.port unless req.standard_port?
38
38
 
39
- req.commit_flash
40
-
41
39
  body = %(<html><body>You are being <a href="#{ERB::Util.unwrapped_html_escape(uri.to_s)}">redirected</a>.</body></html>)
42
40
 
43
41
  headers = {
44
- 'Location' => uri.to_s,
45
- 'Content-Type' => 'text/html',
46
- 'Content-Length' => body.length.to_s
42
+ "Location" => uri.to_s,
43
+ "Content-Type" => "text/html",
44
+ "Content-Length" => body.length.to_s
47
45
  }
48
46
 
49
47
  [ status, headers, [body] ]
@@ -59,19 +57,19 @@ module ActionDispatch
59
57
 
60
58
  private
61
59
  def relative_path?(path)
62
- path && !path.empty? && path[0] != '/'
60
+ path && !path.empty? && path[0] != "/"
63
61
  end
64
62
 
65
63
  def escape(params)
66
- Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
64
+ Hash[params.map { |k, v| [k, Rack::Utils.escape(v)] }]
67
65
  end
68
66
 
69
67
  def escape_fragment(params)
70
- Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_fragment(v)] }]
68
+ Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_fragment(v)] }]
71
69
  end
72
70
 
73
71
  def escape_path(params)
74
- Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_path(v)] }]
72
+ Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_path(v)] }]
75
73
  end
76
74
  end
77
75
 
@@ -105,11 +103,11 @@ module ActionDispatch
105
103
 
106
104
  def path(params, request)
107
105
  url_options = {
108
- :protocol => request.protocol,
109
- :host => request.host,
110
- :port => request.optional_port,
111
- :path => request.path,
112
- :params => request.query_parameters
106
+ protocol: request.protocol,
107
+ host: request.host,
108
+ port: request.optional_port,
109
+ path: request.path,
110
+ params: request.query_parameters
113
111
  }.merge! options
114
112
 
115
113
  if !params.empty? && url_options[:path].match(/%\{\w*\}/)
@@ -130,16 +128,18 @@ module ActionDispatch
130
128
  end
131
129
 
132
130
  def inspect
133
- "redirect(#{status}, #{options.map{ |k,v| "#{k}: #{v}" }.join(', ')})"
131
+ "redirect(#{status}, #{options.map { |k, v| "#{k}: #{v}" }.join(', ')})"
134
132
  end
135
133
  end
136
134
 
137
135
  module Redirection
138
-
139
136
  # Redirect any path to another path:
140
137
  #
141
138
  # get "/stories" => redirect("/posts")
142
139
  #
140
+ # This will redirect the user, while ignoring certain parts of the request, including query string, etc.
141
+ # `/stories`, `/stories?foo=bar`, etc all redirect to `/posts`.
142
+ #
143
143
  # You can also use interpolation in the supplied redirect argument:
144
144
  #
145
145
  # get 'docs/:article', to: redirect('/wiki/%{article}')
@@ -168,6 +168,11 @@ module ActionDispatch
168
168
  #
169
169
  # get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}')
170
170
  # get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')
171
+ # get '/stories', to: redirect(path: '/posts')
172
+ #
173
+ # This will redirect the user, while changing only the specified parts of the request,
174
+ # for example the `path` option in the last example.
175
+ # `/stories`, `/stories?foo=bar`, redirect to `/posts` and `/posts?foo=bar` respectively.
171
176
  #
172
177
  # Finally, an object which responds to call can be supplied to redirect, allowing you to reuse
173
178
  # common redirect routes. The call method must accept two arguments, params and request, and return