actionpack 7.0.2.4 → 7.0.3.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -0
  3. data/lib/abstract_controller/base.rb +6 -5
  4. data/lib/abstract_controller/callbacks.rb +1 -1
  5. data/lib/action_controller/api.rb +5 -5
  6. data/lib/action_controller/base.rb +5 -4
  7. data/lib/action_controller/form_builder.rb +2 -2
  8. data/lib/action_controller/metal/conditional_get.rb +1 -1
  9. data/lib/action_controller/metal/content_security_policy.rb +35 -1
  10. data/lib/action_controller/metal/helpers.rb +1 -1
  11. data/lib/action_controller/metal/http_authentication.rb +56 -29
  12. data/lib/action_controller/metal/live.rb +1 -0
  13. data/lib/action_controller/metal/permissions_policy.rb +18 -27
  14. data/lib/action_controller/metal/redirecting.rb +2 -2
  15. data/lib/action_controller/metal/renderers.rb +10 -11
  16. data/lib/action_controller/metal/rendering.rb +1 -1
  17. data/lib/action_controller/metal/request_forgery_protection.rb +4 -4
  18. data/lib/action_controller/metal/streaming.rb +5 -5
  19. data/lib/action_controller/metal/strong_parameters.rb +6 -2
  20. data/lib/action_controller/metal/url_for.rb +3 -3
  21. data/lib/action_controller/metal.rb +3 -3
  22. data/lib/action_controller/renderer.rb +1 -1
  23. data/lib/action_controller/test_case.rb +3 -3
  24. data/lib/action_controller.rb +1 -0
  25. data/lib/action_dispatch/http/content_security_policy.rb +71 -1
  26. data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
  27. data/lib/action_dispatch/http/permissions_policy.rb +16 -0
  28. data/lib/action_dispatch/http/request.rb +2 -2
  29. data/lib/action_dispatch/middleware/cookies.rb +6 -2
  30. data/lib/action_dispatch/middleware/flash.rb +8 -7
  31. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  32. data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
  33. data/lib/action_dispatch/routing/mapper.rb +4 -4
  34. data/lib/action_dispatch/routing/redirection.rb +5 -0
  35. data/lib/action_dispatch/routing/route_set.rb +3 -1
  36. data/lib/action_dispatch/routing/url_for.rb +3 -3
  37. data/lib/action_dispatch/routing.rb +3 -4
  38. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  39. data/lib/action_pack/gem_version.rb +3 -3
  40. data/lib/action_pack/version.rb +1 -1
  41. metadata +12 -12
@@ -32,7 +32,7 @@ module ActionController # :nodoc:
32
32
  # response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
33
33
  # Ajax) requests are allowed to make requests for JavaScript responses.
34
34
  #
35
- # Subclasses of <tt>ActionController::Base</tt> are protected by default with the
35
+ # Subclasses of ActionController::Base are protected by default with the
36
36
  # <tt>:exception</tt> strategy, which raises an
37
37
  # <tt>ActionController::InvalidAuthenticityToken</tt> error on unverified requests.
38
38
  #
@@ -124,8 +124,8 @@ module ActionController # :nodoc:
124
124
  #
125
125
  # Valid Options:
126
126
  #
127
- # * <tt>:only/:except</tt> - Only apply forgery protection to a subset of actions. For example <tt>only: [ :create, :create_all ]</tt>.
128
- # * <tt>:if/:unless</tt> - Turn off the forgery protection entirely depending on the passed Proc or method reference.
127
+ # * <tt>:only</tt> / <tt>:except</tt> - Only apply forgery protection to a subset of actions. For example <tt>only: [ :create, :create_all ]</tt>.
128
+ # * <tt>:if</tt> / <tt>:unless</tt> - Turn off the forgery protection entirely depending on the passed Proc or method reference.
129
129
  # * <tt>:prepend</tt> - By default, the verification of the authentication token will be added at the position of the
130
130
  # protect_from_forgery call in your application. This means any callbacks added before are run first. This is useful
131
131
  # when you want your forgery protection to depend on other callbacks, like authentication methods (Oauth vs Cookie auth).
@@ -168,7 +168,7 @@ module ActionController # :nodoc:
168
168
  #
169
169
  # See +skip_before_action+ for allowed options.
170
170
  def skip_forgery_protection(options = {})
171
- skip_before_action :verify_authenticity_token, options
171
+ skip_before_action :verify_authenticity_token, options.reverse_merge(raise: false)
172
172
  end
173
173
 
174
174
  private
@@ -24,7 +24,7 @@ module ActionController # :nodoc:
24
24
  # Ruby implementation).
25
25
  #
26
26
  # Streaming can be added to a given template easily, all you need to do is
27
- # to pass the :stream option.
27
+ # to pass the +:stream+ option.
28
28
  #
29
29
  # class PostsController
30
30
  # def index
@@ -59,8 +59,8 @@ module ActionController # :nodoc:
59
59
  # render stream: true
60
60
  # end
61
61
  #
62
- # Notice that :stream only works with templates. Rendering :json
63
- # or :xml with :stream won't work.
62
+ # Notice that +:stream+ only works with templates. Rendering +:json+
63
+ # or +:xml+ with +:stream+ won't work.
64
64
  #
65
65
  # == Communication between layout and template
66
66
  #
@@ -72,7 +72,7 @@ module ActionController # :nodoc:
72
72
  # variables set in the template to be used in the layout, they won't
73
73
  # work once you move to streaming. The proper way to communicate
74
74
  # between layout and template, regardless of whether you use streaming
75
- # or not, is by using +content_for+, +provide+ and +yield+.
75
+ # or not, is by using +content_for+, +provide+, and +yield+.
76
76
  #
77
77
  # Take a simple example where the layout expects the template to tell
78
78
  # which title to use:
@@ -132,7 +132,7 @@ module ActionController # :nodoc:
132
132
  # That said, when streaming, you need to properly check your templates
133
133
  # and choose when to use +provide+ and +content_for+.
134
134
  #
135
- # == Headers, cookies, session and flash
135
+ # == Headers, cookies, session, and flash
136
136
  #
137
137
  # When streaming, the HTTP headers are sent to the client right before
138
138
  # it renders the first line. This means that, modifying headers, cookies,
@@ -236,7 +236,7 @@ module ActionController
236
236
  # By default, never raise an UnpermittedParameters exception if these
237
237
  # params are present. The default includes both 'controller' and 'action'
238
238
  # because they are added by Rails and should be of no concern. One way
239
- # to change these is to specify `always_permitted_parameters` in your
239
+ # to change these is to specify +always_permitted_parameters+ in your
240
240
  # config. For instance:
241
241
  #
242
242
  # config.action_controller.always_permitted_parameters = %w( controller action format )
@@ -778,7 +778,7 @@ module ActionController
778
778
 
779
779
  # Deletes a key-value pair from +Parameters+ and returns the value. If
780
780
  # +key+ is not found, returns +nil+ (or, with optional code block, yields
781
- # +key+ and returns the result). Cf. +#extract!+, which returns the
781
+ # +key+ and returns the result). Cf. #extract!, which returns the
782
782
  # corresponding +ActionController::Parameters+ object.
783
783
  def delete(key, &block)
784
784
  convert_value_to_parameters(@parameters.delete(key, &block))
@@ -908,6 +908,10 @@ module ActionController
908
908
  end
909
909
  end
910
910
 
911
+ def encode_with(coder) # :nodoc:
912
+ coder.map = { "parameters" => @parameters, "permitted" => @permitted }
913
+ end
914
+
911
915
  # Returns duplicate of object including all parameters.
912
916
  def deep_dup
913
917
  self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
@@ -4,11 +4,11 @@ module ActionController
4
4
  # Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
5
5
  # the <tt>_routes</tt> method. Otherwise, an exception will be raised.
6
6
  #
7
- # In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
7
+ # In addition to AbstractController::UrlFor, this module accesses the HTTP layer to define
8
8
  # URL options like the +host+. In order to do so, this module requires the host class
9
9
  # to implement +env+ which needs to be Rack-compatible and +request+
10
- # which is either an instance of +ActionDispatch::Request+ or an object
11
- # that responds to the +host+, +optional_port+, +protocol+ and
10
+ # which is either an instance of ActionDispatch::Request or an object
11
+ # that responds to the +host+, +optional_port+, +protocol+, and
12
12
  # +symbolized_path_parameter+ methods.
13
13
  #
14
14
  # class RootUrl
@@ -60,7 +60,7 @@ module ActionController
60
60
 
61
61
  # <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
62
62
  # valid Rack interface without the additional niceties provided by
63
- # <tt>ActionController::Base</tt>.
63
+ # ActionController::Base.
64
64
  #
65
65
  # A sample metal controller might look like this:
66
66
  #
@@ -111,7 +111,7 @@ module ActionController
111
111
  #
112
112
  # == Other Helpers
113
113
  #
114
- # You can refer to the modules included in <tt>ActionController::Base</tt> to see
114
+ # You can refer to the modules included in ActionController::Base to see
115
115
  # other features you can bring into your metal controller.
116
116
  #
117
117
  class Metal < AbstractController::Base
@@ -137,7 +137,7 @@ module ActionController
137
137
  false
138
138
  end
139
139
 
140
- # Delegates to the class' <tt>controller_name</tt>.
140
+ # Delegates to the class's ::controller_name.
141
141
  def controller_name
142
142
  self.class.controller_name
143
143
  end
@@ -71,7 +71,7 @@ module ActionController
71
71
  # Render templates with any options from ActionController::Base#render_to_string.
72
72
  #
73
73
  # The primary options are:
74
- # * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
74
+ # * <tt>:partial</tt> - See ActionView::PartialRenderer for details.
75
75
  # * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
76
76
  # It shouldn’t be used directly with unsanitized user input due to lack of validation.
77
77
  # * <tt>:inline</tt> - Renders an ERB template string.
@@ -241,7 +241,7 @@ module ActionController
241
241
  # == Basic example
242
242
  #
243
243
  # Functional tests are written as follows:
244
- # 1. First, one uses the +get+, +post+, +patch+, +put+, +delete+ or +head+ method to simulate
244
+ # 1. First, one uses the +get+, +post+, +patch+, +put+, +delete+, or +head+ method to simulate
245
245
  # an HTTP request.
246
246
  # 2. Then, one asserts whether the current state is as expected. "State" can be anything:
247
247
  # the controller's HTTP response, the database contents, etc.
@@ -391,7 +391,7 @@ module ActionController
391
391
  #
392
392
  # You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with
393
393
  # +post+, +patch+, +put+, +delete+, and +head+.
394
- # Example sending parameters, session and setting a flash message:
394
+ # Example sending parameters, session, and setting a flash message:
395
395
  #
396
396
  # get :show,
397
397
  # params: { id: 7 },
@@ -461,7 +461,7 @@ module ActionController
461
461
  # session: { user_id: 1 },
462
462
  # flash: { notice: 'This is flash message' }
463
463
  #
464
- # To simulate +GET+, +POST+, +PATCH+, +PUT+, +DELETE+ and +HEAD+ requests
464
+ # To simulate +GET+, +POST+, +PATCH+, +PUT+, +DELETE+, and +HEAD+ requests
465
465
  # prefer using #get, #post, #patch, #put, #delete and #head methods
466
466
  # respectively which will make tests more expressive.
467
467
  #
@@ -3,6 +3,7 @@
3
3
  require "abstract_controller"
4
4
  require "action_dispatch"
5
5
  require "action_controller/metal/strong_parameters"
6
+ require "action_controller/metal/exceptions"
6
7
 
7
8
  module ActionController
8
9
  extend ActiveSupport::Autoload
@@ -1,8 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
+ require "active_support/core_ext/array/wrap"
4
5
 
5
6
  module ActionDispatch # :nodoc:
7
+ # Configures the HTTP
8
+ # {Content-Security-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy]
9
+ # response header to help protect against XSS and injection attacks.
10
+ #
11
+ # Example global policy:
12
+ #
13
+ # Rails.application.config.content_security_policy do |policy|
14
+ # policy.default_src :self, :https
15
+ # policy.font_src :self, :https, :data
16
+ # policy.img_src :self, :https, :data
17
+ # policy.object_src :none
18
+ # policy.script_src :self, :https
19
+ # policy.style_src :self, :https
20
+ #
21
+ # # Specify URI for violation reports
22
+ # policy.report_uri "/csp-violation-report-endpoint"
23
+ # end
6
24
  class ContentSecurityPolicy
7
25
  class Middleware
8
26
  CONTENT_TYPE = "Content-Type"
@@ -167,6 +185,15 @@ module ActionDispatch # :nodoc:
167
185
  end
168
186
  end
169
187
 
188
+ # Specify whether to prevent the user agent from loading any assets over
189
+ # HTTP when the page uses HTTPS:
190
+ #
191
+ # policy.block_all_mixed_content
192
+ #
193
+ # Pass +false+ to allow it again:
194
+ #
195
+ # policy.block_all_mixed_content false
196
+ #
170
197
  def block_all_mixed_content(enabled = true)
171
198
  if enabled
172
199
  @directives["block-all-mixed-content"] = true
@@ -175,6 +202,14 @@ module ActionDispatch # :nodoc:
175
202
  end
176
203
  end
177
204
 
205
+ # Restricts the set of plugins that can be embedded:
206
+ #
207
+ # policy.plugin_types "application/x-shockwave-flash"
208
+ #
209
+ # Leave empty to allow all plugins:
210
+ #
211
+ # policy.plugin_types
212
+ #
178
213
  def plugin_types(*types)
179
214
  if types.first
180
215
  @directives["plugin-types"] = types
@@ -183,10 +218,24 @@ module ActionDispatch # :nodoc:
183
218
  end
184
219
  end
185
220
 
221
+ # Enable the {report-uri}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri]
222
+ # directive. Violation reports will be sent to the specified URI:
223
+ #
224
+ # policy.report_uri "/csp-violation-report-endpoint"
225
+ #
186
226
  def report_uri(uri)
187
227
  @directives["report-uri"] = [uri]
188
228
  end
189
229
 
230
+ # Specify asset types for which {Subresource Integrity}[https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity]
231
+ # is required:
232
+ #
233
+ # policy.require_sri_for :script, :style
234
+ #
235
+ # Leave empty to not require Subresource Integrity:
236
+ #
237
+ # policy.require_sri_for
238
+ #
190
239
  def require_sri_for(*types)
191
240
  if types.first
192
241
  @directives["require-sri-for"] = types
@@ -195,6 +244,19 @@ module ActionDispatch # :nodoc:
195
244
  end
196
245
  end
197
246
 
247
+ # Specify whether a {sandbox}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox]
248
+ # should be enabled for the requested resource:
249
+ #
250
+ # policy.sandbox
251
+ #
252
+ # Values can be passed as arguments:
253
+ #
254
+ # policy.sandbox "allow-scripts", "allow-modals"
255
+ #
256
+ # Pass +false+ to disable the sandbox:
257
+ #
258
+ # policy.sandbox false
259
+ #
198
260
  def sandbox(*values)
199
261
  if values.empty?
200
262
  @directives["sandbox"] = true
@@ -205,6 +267,14 @@ module ActionDispatch # :nodoc:
205
267
  end
206
268
  end
207
269
 
270
+ # Specify whether user agents should treat any assets over HTTP as HTTPS:
271
+ #
272
+ # policy.upgrade_insecure_requests
273
+ #
274
+ # Pass +false+ to disable it:
275
+ #
276
+ # policy.upgrade_insecure_requests false
277
+ #
208
278
  def upgrade_insecure_requests(enabled = true)
209
279
  if enabled
210
280
  @directives["upgrade-insecure-requests"] = true
@@ -269,7 +339,7 @@ module ActionDispatch # :nodoc:
269
339
  raise RuntimeError, "Missing context for the dynamic content security policy source: #{source.inspect}"
270
340
  else
271
341
  resolved = context.instance_exec(&source)
272
- resolved.is_a?(Symbol) ? apply_mapping(resolved) : resolved
342
+ apply_mappings(Array.wrap(resolved))
273
343
  end
274
344
  else
275
345
  raise RuntimeError, "Unexpected content security policy source: #{source.inspect}"
@@ -132,8 +132,8 @@ module ActionDispatch
132
132
  # Sets the \formats by string extensions. This differs from #format= by allowing you
133
133
  # to set multiple, ordered formats, which is useful when you want to have a fallback.
134
134
  #
135
- # In this example, the :iphone format will be used if it's available, otherwise it'll fallback
136
- # to the :html format.
135
+ # In this example, the +:iphone+ format will be used if it's available, otherwise it'll fallback
136
+ # to the +:html+ format.
137
137
  #
138
138
  # class ApplicationController < ActionController::Base
139
139
  # before_action :adjust_format_for_iphone_with_html_fallback
@@ -3,6 +3,22 @@
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
5
  module ActionDispatch # :nodoc:
6
+ # Configures the HTTP
7
+ # {Feature-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy]
8
+ # response header to specify which browser features the current document and
9
+ # its iframes can use.
10
+ #
11
+ # Example global policy:
12
+ #
13
+ # Rails.application.config.permissions_policy do |policy|
14
+ # policy.camera :none
15
+ # policy.gyroscope :none
16
+ # policy.microphone :none
17
+ # policy.usb :none
18
+ # policy.fullscreen :self
19
+ # policy.payment :self, "https://secure.example.com"
20
+ # end
21
+ #
6
22
  class PermissionsPolicy
7
23
  class Middleware
8
24
  CONTENT_TYPE = "Content-Type"
@@ -298,8 +298,8 @@ module ActionDispatch
298
298
  ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
299
299
 
300
300
  # Returns the unique request id, which is based on either the X-Request-Id header that can
301
- # be generated by a firewall, load balancer, or web server or by the RequestId middleware
302
- # (which sets the action_dispatch.request_id environment variable).
301
+ # be generated by a firewall, load balancer, or web server, or by the RequestId middleware
302
+ # (which sets the +action_dispatch.request_id+ environment variable).
303
303
  #
304
304
  # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
305
305
  # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
@@ -139,7 +139,7 @@ module ActionDispatch
139
139
  #
140
140
  # cookies.delete :user_name
141
141
  #
142
- # Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
142
+ # Please note that if you specify a +:domain+ when setting a cookie, you must also specify the domain when deleting the cookie:
143
143
  #
144
144
  # cookies[:name] = {
145
145
  # value: 'a yummy cookie',
@@ -176,6 +176,10 @@ module ActionDispatch
176
176
  # Default is +false+.
177
177
  # * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
178
178
  # only HTTP. Defaults to +false+.
179
+ # * <tt>:same_site</tt> - The value of the +SameSite+ cookie attribute, which
180
+ # determines how this cookie should be restricted in cross-site contexts.
181
+ # Possible values are +nil+, +:none+, +:lax+, and +:strict+. Defaults to
182
+ # +:lax+.
179
183
  class Cookies
180
184
  HTTP_HEADER = "Set-Cookie"
181
185
  GENERATOR_KEY = "action_dispatch.key_generator"
@@ -199,7 +203,7 @@ module ActionDispatch
199
203
  # Raised when storing more than 4K of session data.
200
204
  CookieOverflow = Class.new StandardError
201
205
 
202
- # Include in a cookie jar to allow chaining, e.g. cookies.permanent.signed.
206
+ # Include in a cookie jar to allow chaining, e.g. +cookies.permanent.signed+.
203
207
  module ChainedCookieJars
204
208
  # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example:
205
209
  #
@@ -20,10 +20,11 @@ module ActionDispatch
20
20
  # end
21
21
  # end
22
22
  #
23
- # show.html.erb
24
- # <% if flash[:notice] %>
25
- # <div class="notice"><%= flash[:notice] %></div>
26
- # <% end %>
23
+ # Then in +show.html.erb+:
24
+ #
25
+ # <% if flash[:notice] %>
26
+ # <div class="notice"><%= flash[:notice] %></div>
27
+ # <% end %>
27
28
  #
28
29
  # Since the +notice+ and +alert+ keys are a common idiom, convenience accessors are available:
29
30
  #
@@ -41,9 +42,9 @@ module ActionDispatch
41
42
  KEY = "action_dispatch.request.flash_hash"
42
43
 
43
44
  module RequestMethods
44
- # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
45
- # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
46
- # to put a new one.
45
+ # Access the contents of the flash. Returns a ActionDispatch::Flash::FlashHash.
46
+ #
47
+ # See ActionDispatch::Flash for example usage.
47
48
  def flash
48
49
  flash = flash_hash
49
50
  return flash if flash
@@ -5,7 +5,7 @@ require "active_support/core_ext/string/access"
5
5
 
6
6
  module ActionDispatch
7
7
  # Makes a unique request id available to the +action_dispatch.request_id+ env variable (which is then accessible
8
- # through <tt>ActionDispatch::Request#request_id</tt> or the alias <tt>ActionDispatch::Request#uuid</tt>) and sends
8
+ # through ActionDispatch::Request#request_id or the alias ActionDispatch::Request#uuid) and sends
9
9
  # the same id to the client via the X-Request-Id header.
10
10
  #
11
11
  # The unique request id is either based on the X-Request-Id header in the request, which would typically be generated
@@ -44,8 +44,8 @@ module ActionDispatch
44
44
  # Rails.application.config.session_store :cookie_store, expire_after: 14.days
45
45
  #
46
46
  # would set the session cookie to expire automatically 14 days after creation.
47
- # Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
48
- # <tt>:httponly</tt>.
47
+ # Other useful options include <tt>:key</tt>, <tt>:secure</tt>,
48
+ # <tt>:httponly</tt>, and <tt>:same_site</tt>.
49
49
  class CookieStore < AbstractSecureStore
50
50
  class SessionId < DelegateClass(Rack::Session::SessionId)
51
51
  attr_reader :cookie_value
@@ -390,10 +390,10 @@ module ActionDispatch
390
390
  #
391
391
  # If you want to expose your action to both GET and POST, use:
392
392
  #
393
- # # sets :controller, :action and :id in params
393
+ # # sets :controller, :action, and :id in params
394
394
  # match ':controller/:action/:id', via: [:get, :post]
395
395
  #
396
- # Note that +:controller+, +:action+ and +:id+ are interpreted as URL
396
+ # Note that +:controller+, +:action+, and +:id+ are interpreted as URL
397
397
  # query parameters and thus available through +params+ in an action.
398
398
  #
399
399
  # If you want to expose your action to GET, use +get+ in the router:
@@ -906,7 +906,7 @@ module ActionDispatch
906
906
  #
907
907
  # === Options
908
908
  #
909
- # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+
909
+ # The +:path+, +:as+, +:module+, +:shallow_path+, and +:shallow_prefix+
910
910
  # options all default to the name of the namespace.
911
911
  #
912
912
  # For options, see <tt>Base#match</tt>. For +:shallow_path+ option, see
@@ -1082,7 +1082,7 @@ module ActionDispatch
1082
1082
 
1083
1083
  # Resource routing allows you to quickly declare all of the common routes
1084
1084
  # for a given resourceful controller. Instead of declaring separate routes
1085
- # for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+
1085
+ # for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
1086
1086
  # actions, a resourceful route declares them in a single line of code:
1087
1087
  #
1088
1088
  # resources :photos
@@ -142,6 +142,11 @@ module ActionDispatch
142
142
  # This will redirect the user, while ignoring certain parts of the request, including query string, etc.
143
143
  # <tt>/stories</tt>, <tt>/stories?foo=bar</tt>, etc all redirect to <tt>/posts</tt>.
144
144
  #
145
+ # The redirect will use a <tt>301 Moved Permanently</tt> status code by
146
+ # default. This can be overridden with the +:status+ option:
147
+ #
148
+ # get "/stories" => redirect("/posts", status: 307)
149
+ #
145
150
  # You can also use interpolation in the supplied redirect argument:
146
151
  #
147
152
  # get 'docs/:article', to: redirect('/wiki/%{article}')
@@ -196,7 +196,9 @@ module ActionDispatch
196
196
  def call(t, method_name, args, inner_options, url_strategy)
197
197
  if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
198
198
  options = t.url_options.merge @options
199
- options[:path] = optimized_helper(args)
199
+ path = optimized_helper(args)
200
+ path << "/" if options[:trailing_slash] && !path.end_with?("/")
201
+ options[:path] = path
200
202
 
201
203
  original_script_name = options.delete(:original_script_name)
202
204
  script_name = t._routes.find_script_name(options)
@@ -70,7 +70,7 @@ module ActionDispatch
70
70
  # resources :users
71
71
  #
72
72
  # This generates, among other things, the method <tt>users_path</tt>. By default,
73
- # this method is accessible from your controllers, views and mailers. If you need
73
+ # this method is accessible from your controllers, views, and mailers. If you need
74
74
  # to access this auto-generated method from other places (such as a model), then
75
75
  # you can do that by including Rails.application.routes.url_helpers in your class:
76
76
  #
@@ -115,7 +115,7 @@ module ActionDispatch
115
115
  default_url_options
116
116
  end
117
117
 
118
- # Generate a URL based on the options provided, default_url_options and the
118
+ # Generate a URL based on the options provided, default_url_options, and the
119
119
  # routes defined in routes.rb. The following options are supported:
120
120
  #
121
121
  # * <tt>:only_path</tt> - If true, the relative URL is returned. Defaults to +false+.
@@ -154,7 +154,7 @@ module ActionDispatch
154
154
  # # => '/myapp/tasks/testing'
155
155
  #
156
156
  # Missing routes keys may be filled in from the current request's parameters
157
- # (e.g. +:controller+, +:action+, +:id+ and any other parameters that are
157
+ # (e.g. +:controller+, +:action+, +:id+, and any other parameters that are
158
158
  # placed in the path). Given that the current action has been reached
159
159
  # through <tt>GET /users/1</tt>:
160
160
  #
@@ -28,7 +28,7 @@ module ActionDispatch
28
28
  #
29
29
  # Resource routing allows you to quickly declare all of the common routes
30
30
  # for a given resourceful controller. Instead of declaring separate routes
31
- # for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+
31
+ # for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
32
32
  # actions, a resourceful route declares them in a single line of code:
33
33
  #
34
34
  # resources :photos
@@ -65,9 +65,8 @@ module ActionDispatch
65
65
  # resources :posts, :comments
66
66
  # end
67
67
  #
68
- # For more, see <tt>Routing::Mapper::Resources#resources</tt>,
69
- # <tt>Routing::Mapper::Scoping#namespace</tt>, and
70
- # <tt>Routing::Mapper::Scoping#scope</tt>.
68
+ # For more, see Routing::Mapper::Resources#resources,
69
+ # Routing::Mapper::Scoping#namespace, and Routing::Mapper::Scoping#scope.
71
70
  #
72
71
  # == Non-resourceful routes
73
72
  #
@@ -18,8 +18,8 @@ module ActionDispatch
18
18
  # match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
19
19
  #
20
20
  # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
21
- # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
22
- # and a :method containing the required HTTP verb.
21
+ # requiring a specific HTTP method. The hash should contain a +:path+ with the incoming request path
22
+ # and a +:method+ containing the required HTTP verb.
23
23
  #
24
24
  # # Asserts that POSTing to /items will call the create action on ItemsController
25
25
  # assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
@@ -187,6 +187,7 @@ module ActionDispatch
187
187
  super
188
188
  end
189
189
  end
190
+ ruby2_keywords(:method_missing)
190
191
 
191
192
  private
192
193
  # Recognizes the route for a given path.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionPack
4
- # Returns the version of the currently loaded Action Pack as a <tt>Gem::Version</tt>
4
+ # Returns the currently loaded version of Action Pack as a <tt>Gem::Version</tt>.
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION::STRING
7
7
  end
@@ -9,8 +9,8 @@ module ActionPack
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 2
13
- PRE = "4"
12
+ TINY = 3
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module ActionPack
6
- # Returns the version of the currently loaded ActionPack as a <tt>Gem::Version</tt>
6
+ # Returns the currently loaded version of Action Pack as a <tt>Gem::Version</tt>.
7
7
  def self.version
8
8
  gem_version
9
9
  end