actionpack 7.1.5.1 → 8.1.2

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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +308 -523
  3. data/README.rdoc +1 -1
  4. data/lib/abstract_controller/asset_paths.rb +6 -2
  5. data/lib/abstract_controller/base.rb +104 -105
  6. data/lib/abstract_controller/caching/fragments.rb +50 -53
  7. data/lib/abstract_controller/caching.rb +8 -3
  8. data/lib/abstract_controller/callbacks.rb +70 -62
  9. data/lib/abstract_controller/collector.rb +7 -7
  10. data/lib/abstract_controller/deprecator.rb +2 -0
  11. data/lib/abstract_controller/error.rb +2 -0
  12. data/lib/abstract_controller/helpers.rb +71 -84
  13. data/lib/abstract_controller/logger.rb +4 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/rendering.rb +13 -13
  16. data/lib/abstract_controller/translation.rb +12 -13
  17. data/lib/abstract_controller/url_for.rb +8 -6
  18. data/lib/abstract_controller.rb +2 -0
  19. data/lib/action_controller/api/api_rendering.rb +2 -0
  20. data/lib/action_controller/api.rb +76 -72
  21. data/lib/action_controller/base.rb +199 -126
  22. data/lib/action_controller/caching.rb +16 -14
  23. data/lib/action_controller/deprecator.rb +2 -0
  24. data/lib/action_controller/form_builder.rb +21 -18
  25. data/lib/action_controller/log_subscriber.rb +23 -2
  26. data/lib/action_controller/metal/allow_browser.rb +133 -0
  27. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  28. data/lib/action_controller/metal/conditional_get.rb +217 -175
  29. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  30. data/lib/action_controller/metal/cookies.rb +4 -2
  31. data/lib/action_controller/metal/data_streaming.rb +72 -63
  32. data/lib/action_controller/metal/default_headers.rb +5 -3
  33. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  34. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  35. data/lib/action_controller/metal/exceptions.rb +16 -9
  36. data/lib/action_controller/metal/flash.rb +13 -14
  37. data/lib/action_controller/metal/head.rb +15 -11
  38. data/lib/action_controller/metal/helpers.rb +63 -55
  39. data/lib/action_controller/metal/http_authentication.rb +209 -201
  40. data/lib/action_controller/metal/implicit_render.rb +17 -15
  41. data/lib/action_controller/metal/instrumentation.rb +16 -14
  42. data/lib/action_controller/metal/live.rb +177 -128
  43. data/lib/action_controller/metal/logging.rb +6 -4
  44. data/lib/action_controller/metal/mime_responds.rb +151 -142
  45. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  46. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  47. data/lib/action_controller/metal/permissions_policy.rb +22 -12
  48. data/lib/action_controller/metal/rate_limiting.rb +92 -0
  49. data/lib/action_controller/metal/redirecting.rb +213 -94
  50. data/lib/action_controller/metal/renderers.rb +78 -57
  51. data/lib/action_controller/metal/rendering.rb +111 -77
  52. data/lib/action_controller/metal/request_forgery_protection.rb +182 -143
  53. data/lib/action_controller/metal/rescue.rb +20 -9
  54. data/lib/action_controller/metal/streaming.rb +118 -195
  55. data/lib/action_controller/metal/strong_parameters.rb +720 -530
  56. data/lib/action_controller/metal/testing.rb +2 -0
  57. data/lib/action_controller/metal/url_for.rb +17 -15
  58. data/lib/action_controller/metal.rb +86 -60
  59. data/lib/action_controller/railtie.rb +36 -15
  60. data/lib/action_controller/railties/helpers.rb +2 -0
  61. data/lib/action_controller/renderer.rb +41 -36
  62. data/lib/action_controller/structured_event_subscriber.rb +116 -0
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +160 -131
  65. data/lib/action_controller.rb +5 -1
  66. data/lib/action_dispatch/constants.rb +8 -0
  67. data/lib/action_dispatch/deprecator.rb +2 -0
  68. data/lib/action_dispatch/http/cache.rb +163 -35
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +54 -39
  71. data/lib/action_dispatch/http/filter_parameters.rb +14 -8
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +22 -22
  74. data/lib/action_dispatch/http/mime_negotiation.rb +89 -41
  75. data/lib/action_dispatch/http/mime_type.rb +25 -21
  76. data/lib/action_dispatch/http/mime_types.rb +3 -0
  77. data/lib/action_dispatch/http/param_builder.rb +187 -0
  78. data/lib/action_dispatch/http/param_error.rb +26 -0
  79. data/lib/action_dispatch/http/parameters.rb +14 -12
  80. data/lib/action_dispatch/http/permissions_policy.rb +25 -36
  81. data/lib/action_dispatch/http/query_parser.rb +55 -0
  82. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  83. data/lib/action_dispatch/http/request.rb +141 -92
  84. data/lib/action_dispatch/http/response.rb +137 -77
  85. data/lib/action_dispatch/http/upload.rb +18 -16
  86. data/lib/action_dispatch/http/url.rb +187 -89
  87. data/lib/action_dispatch/journey/formatter.rb +21 -9
  88. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  89. data/lib/action_dispatch/journey/gtg/simulator.rb +34 -11
  90. data/lib/action_dispatch/journey/gtg/transition_table.rb +47 -53
  91. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  92. data/lib/action_dispatch/journey/nodes/node.rb +8 -6
  93. data/lib/action_dispatch/journey/parser.rb +99 -195
  94. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  95. data/lib/action_dispatch/journey/route.rb +54 -38
  96. data/lib/action_dispatch/journey/router/utils.rb +22 -27
  97. data/lib/action_dispatch/journey/router.rb +63 -83
  98. data/lib/action_dispatch/journey/routes.rb +11 -2
  99. data/lib/action_dispatch/journey/scanner.rb +46 -42
  100. data/lib/action_dispatch/journey/visitors.rb +57 -23
  101. data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
  102. data/lib/action_dispatch/journey.rb +2 -0
  103. data/lib/action_dispatch/log_subscriber.rb +7 -1
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  106. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  107. data/lib/action_dispatch/middleware/cookies.rb +125 -106
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +37 -8
  109. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  110. data/lib/action_dispatch/middleware/debug_view.rb +13 -5
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +18 -23
  112. data/lib/action_dispatch/middleware/executor.rb +19 -4
  113. data/lib/action_dispatch/middleware/flash.rb +63 -51
  114. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +14 -12
  116. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  117. data/lib/action_dispatch/middleware/remote_ip.rb +87 -77
  118. data/lib/action_dispatch/middleware/request_id.rb +16 -10
  119. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +30 -8
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +16 -16
  125. data/lib/action_dispatch/middleware/ssl.rb +53 -40
  126. data/lib/action_dispatch/middleware/stack.rb +11 -10
  127. data/lib/action_dispatch/middleware/static.rb +33 -31
  128. data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -5
  130. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
  131. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
  136. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
  139. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
  140. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
  141. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  142. data/lib/action_dispatch/railtie.rb +23 -3
  143. data/lib/action_dispatch/request/session.rb +24 -21
  144. data/lib/action_dispatch/request/utils.rb +11 -3
  145. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  146. data/lib/action_dispatch/routing/inspector.rb +85 -60
  147. data/lib/action_dispatch/routing/mapper.rb +1031 -851
  148. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  149. data/lib/action_dispatch/routing/redirection.rb +47 -39
  150. data/lib/action_dispatch/routing/route_set.rb +79 -56
  151. data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
  152. data/lib/action_dispatch/routing/url_for.rb +130 -125
  153. data/lib/action_dispatch/routing.rb +150 -148
  154. data/lib/action_dispatch/structured_event_subscriber.rb +20 -0
  155. data/lib/action_dispatch/system_test_case.rb +91 -81
  156. data/lib/action_dispatch/system_testing/browser.rb +16 -23
  157. data/lib/action_dispatch/system_testing/driver.rb +2 -0
  158. data/lib/action_dispatch/system_testing/server.rb +2 -0
  159. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +34 -23
  160. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  161. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  162. data/lib/action_dispatch/testing/assertions/response.rb +52 -25
  163. data/lib/action_dispatch/testing/assertions/routing.rb +168 -87
  164. data/lib/action_dispatch/testing/assertions.rb +2 -0
  165. data/lib/action_dispatch/testing/integration.rb +233 -223
  166. data/lib/action_dispatch/testing/request_encoder.rb +11 -9
  167. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  168. data/lib/action_dispatch/testing/test_process.rb +11 -8
  169. data/lib/action_dispatch/testing/test_request.rb +3 -1
  170. data/lib/action_dispatch/testing/test_response.rb +27 -26
  171. data/lib/action_dispatch.rb +36 -32
  172. data/lib/action_pack/gem_version.rb +6 -4
  173. data/lib/action_pack/version.rb +3 -1
  174. data/lib/action_pack.rb +17 -16
  175. metadata +36 -32
  176. data/lib/action_dispatch/journey/parser.y +0 -50
  177. data/lib/action_dispatch/journey/parser_extras.rb +0 -31
@@ -1,170 +1,209 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_view"
4
6
  require "action_controller/log_subscriber"
7
+ require "action_controller/structured_event_subscriber"
5
8
  require "action_controller/metal/params_wrapper"
6
9
 
7
10
  module ActionController
8
- # = Action Controller \Base
11
+ # # Action Controller Base
9
12
  #
10
- # Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
11
- # on request and then either it renders a template or redirects to another action. An action is defined as a public method
12
- # on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
13
+ # Action Controllers are the core of a web request in Rails. They are made up of
14
+ # one or more actions that are executed on request and then either it renders a
15
+ # template or redirects to another action. An action is defined as a public
16
+ # method on the controller, which will automatically be made accessible to the
17
+ # web-server through Rails Routes.
13
18
  #
14
- # By default, only the ApplicationController in a \Rails application inherits from +ActionController::Base+. All other
15
- # controllers inherit from ApplicationController. This gives you one class to configure things such as
19
+ # By default, only the ApplicationController in a Rails application inherits
20
+ # from `ActionController::Base`. All other controllers inherit from
21
+ # ApplicationController. This gives you one class to configure things such as
16
22
  # request forgery protection and filtering of sensitive request parameters.
17
23
  #
18
24
  # A sample controller could look like this:
19
25
  #
20
- # class PostsController < ApplicationController
21
- # def index
22
- # @posts = Post.all
23
- # end
26
+ # class PostsController < ApplicationController
27
+ # def index
28
+ # @posts = Post.all
29
+ # end
24
30
  #
25
- # def create
26
- # @post = Post.create params[:post]
27
- # redirect_to posts_path
31
+ # def create
32
+ # @post = Post.create params[:post]
33
+ # redirect_to posts_path
34
+ # end
28
35
  # end
29
- # end
30
36
  #
31
- # Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action
32
- # after executing code in the action. For example, the +index+ action of the PostsController would render the
33
- # template <tt>app/views/posts/index.html.erb</tt> by default after populating the <tt>@posts</tt> instance variable.
37
+ # Actions, by default, render a template in the `app/views` directory
38
+ # corresponding to the name of the controller and action after executing code in
39
+ # the action. For example, the `index` action of the PostsController would
40
+ # render the template `app/views/posts/index.html.erb` by default after
41
+ # populating the `@posts` instance variable.
34
42
  #
35
- # Unlike index, the create action will not render a template. After performing its main purpose (creating a
36
- # new post), it initiates a redirect instead. This redirect works by returning an external
37
- # <tt>302 Moved</tt> HTTP response that takes the user to the index action.
43
+ # Unlike index, the create action will not render a template. After performing
44
+ # its main purpose (creating a new post), it initiates a redirect instead. This
45
+ # redirect works by returning an external `302 Moved` HTTP response that takes
46
+ # the user to the index action.
38
47
  #
39
- # These two methods represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect.
40
- # Most actions are variations on these themes.
48
+ # These two methods represent the two basic action archetypes used in Action
49
+ # Controllers: Get-and-show and do-and-redirect. Most actions are variations on
50
+ # these themes.
41
51
  #
42
- # == Requests
52
+ # ## Requests
43
53
  #
44
- # For every request, the router determines the value of the +controller+ and +action+ keys. These determine which controller
45
- # and action are called. The remaining request parameters, the session (if one is available), and the full request with
46
- # all the HTTP headers are made available to the action through accessor methods. Then the action is performed.
54
+ # For every request, the router determines the value of the `controller` and
55
+ # `action` keys. These determine which controller and action are called. The
56
+ # remaining request parameters, the session (if one is available), and the full
57
+ # request with all the HTTP headers are made available to the action through
58
+ # accessor methods. Then the action is performed.
47
59
  #
48
- # The full request object is available via the request accessor and is primarily used to query for HTTP headers:
60
+ # The full request object is available via the request accessor and is primarily
61
+ # used to query for HTTP headers:
49
62
  #
50
- # def server_ip
51
- # location = request.env["REMOTE_ADDR"]
52
- # render plain: "This server hosted at #{location}"
53
- # end
63
+ # def server_ip
64
+ # location = request.env["REMOTE_ADDR"]
65
+ # render plain: "This server hosted at #{location}"
66
+ # end
54
67
  #
55
- # == Parameters
68
+ # ## Parameters
56
69
  #
57
- # All request parameters, whether they come from a query string in the URL or form data submitted through a POST request are
58
- # available through the <tt>params</tt> method which returns a hash. For example, an action that was performed through
59
- # <tt>/posts?category=All&limit=5</tt> will include <tt>{ "category" => "All", "limit" => "5" }</tt> in <tt>params</tt>.
70
+ # All request parameters, whether they come from a query string in the URL or
71
+ # form data submitted through a POST request are available through the `params`
72
+ # method which returns a hash. For example, an action that was performed through
73
+ # `/posts?category=All&limit=5` will include `{ "category" => "All", "limit" =>
74
+ # "5" }` in `params`.
60
75
  #
61
- # It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as:
76
+ # It's also possible to construct multi-dimensional parameter hashes by
77
+ # specifying keys using brackets, such as:
62
78
  #
63
- # <input type="text" name="post[name]" value="david">
64
- # <input type="text" name="post[address]" value="hyacintvej">
79
+ # <input type="text" name="post[name]" value="david">
80
+ # <input type="text" name="post[address]" value="hyacintvej">
65
81
  #
66
- # A request coming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
67
- # If the address input had been named <tt>post[address][street]</tt>, the <tt>params</tt> would have included
68
- # <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
82
+ # A request coming from a form holding these inputs will include `{ "post" => {
83
+ # "name" => "david", "address" => "hyacintvej" } }`. If the address input had
84
+ # been named `post[address][street]`, the `params` would have included `{ "post"
85
+ # => { "address" => { "street" => "hyacintvej" } } }`. There's no limit to the
86
+ # depth of the nesting.
69
87
  #
70
- # == Sessions
88
+ # ## Sessions
71
89
  #
72
- # Sessions allow you to store objects in between requests. This is useful for objects that are not yet ready to be persisted,
73
- # such as a Signup object constructed in a multi-paged process, or objects that don't change much and are needed all the time, such
74
- # as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely
75
- # they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at.
90
+ # Sessions allow you to store objects in between requests. This is useful for
91
+ # objects that are not yet ready to be persisted, such as a Signup object
92
+ # constructed in a multi-paged process, or objects that don't change much and
93
+ # are needed all the time, such as a User object for a system that requires
94
+ # login. The session should not be used, however, as a cache for objects where
95
+ # it's likely they could be changed unknowingly. It's usually too much work to
96
+ # keep it all synchronized -- something databases already excel at.
76
97
  #
77
- # You can place objects in the session by using the <tt>session</tt> method, which accesses a hash:
98
+ # You can place objects in the session by using the `session` method, which
99
+ # accesses a hash:
78
100
  #
79
- # session[:person] = Person.authenticate(user_name, password)
101
+ # session[:person] = Person.authenticate(user_name, password)
80
102
  #
81
103
  # You can retrieve it again through the same hash:
82
104
  #
83
- # "Hello #{session[:person]}"
105
+ # "Hello #{session[:person]}"
84
106
  #
85
- # For removing objects from the session, you can either assign a single key to +nil+:
107
+ # For removing objects from the session, you can either assign a single key to
108
+ # `nil`:
86
109
  #
87
- # # removes :person from session
88
- # session[:person] = nil
110
+ # # removes :person from session
111
+ # session[:person] = nil
89
112
  #
90
- # or you can remove the entire session with +reset_session+.
113
+ # or you can remove the entire session with `reset_session`.
91
114
  #
92
115
  # By default, sessions are stored in an encrypted browser cookie (see
93
- # ActionDispatch::Session::CookieStore). Thus the user will not be able to
94
- # read or edit the session data. However, the user can keep a copy of the
95
- # cookie even after it has expired, so you should avoid storing sensitive
96
- # information in cookie-based sessions.
116
+ # ActionDispatch::Session::CookieStore). Thus the user will not be able to read
117
+ # or edit the session data. However, the user can keep a copy of the cookie even
118
+ # after it has expired, so you should avoid storing sensitive information in
119
+ # cookie-based sessions.
97
120
  #
98
- # == Responses
121
+ # ## Responses
99
122
  #
100
- # Each action results in a response, which holds the headers and document to be sent to the user's browser. The actual response
101
- # object is generated automatically through the use of renders and redirects and requires no user intervention.
123
+ # Each action results in a response, which holds the headers and document to be
124
+ # sent to the user's browser. The actual response object is generated
125
+ # automatically through the use of renders and redirects and requires no user
126
+ # intervention.
102
127
  #
103
- # == Renders
128
+ # ## Renders
104
129
  #
105
- # Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering
106
- # of a template. Included in the Action Pack is the Action View, which enables rendering of ERB templates. It's automatically configured.
107
- # The controller passes objects to the view by assigning instance variables:
130
+ # Action Controller sends content to the user by using one of five rendering
131
+ # methods. The most versatile and common is the rendering of a template.
132
+ # Also included with \Rails is Action View, which enables rendering of ERB
133
+ # templates. It's automatically configured. The controller passes objects to the
134
+ # view by assigning instance variables:
108
135
  #
109
- # def show
110
- # @post = Post.find(params[:id])
111
- # end
136
+ # def show
137
+ # @post = Post.find(params[:id])
138
+ # end
112
139
  #
113
140
  # Which are then automatically available to the view:
114
141
  #
115
- # Title: <%= @post.title %>
142
+ # Title: <%= @post.title %>
116
143
  #
117
- # You don't have to rely on the automated rendering. For example, actions that could result in the rendering of different templates
118
- # will use the manual rendering methods:
144
+ # You don't have to rely on the automated rendering. For example, actions that
145
+ # could result in the rendering of different templates will use the manual
146
+ # rendering methods:
119
147
  #
120
- # def search
121
- # @results = Search.find(params[:query])
122
- # case @results.count
123
- # when 0 then render action: "no_results"
124
- # when 1 then render action: "show"
125
- # when 2..10 then render action: "show_many"
148
+ # def search
149
+ # @results = Search.find(params[:query])
150
+ # case @results.count
151
+ # when 0 then render action: "no_results"
152
+ # when 1 then render action: "show"
153
+ # when 2..10 then render action: "show_many"
154
+ # end
126
155
  # end
127
- # end
128
156
  #
129
157
  # Read more about writing ERB and Builder templates in ActionView::Base.
130
158
  #
131
- # == Redirects
159
+ # ## Redirects
132
160
  #
133
- # Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to the
134
- # database, we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're
135
- # going to reuse (and redirect to) a <tt>show</tt> action that we'll assume has already been created. The code might look like this:
161
+ # Redirects are used to move from one action to another. For example, after a
162
+ # `create` action, which stores a blog entry to the database, we might like to
163
+ # show the user the new entry. Because we're following good DRY principles
164
+ # (Don't Repeat Yourself), we're going to reuse (and redirect to) a `show`
165
+ # action that we'll assume has already been created. The code might look like
166
+ # this:
136
167
  #
137
- # def create
138
- # @entry = Entry.new(params[:entry])
139
- # if @entry.save
140
- # # The entry was saved correctly, redirect to show
141
- # redirect_to action: 'show', id: @entry.id
142
- # else
143
- # # things didn't go so well, do something else
168
+ # def create
169
+ # @entry = Entry.new(params[:entry])
170
+ # if @entry.save
171
+ # # The entry was saved correctly, redirect to show
172
+ # redirect_to action: 'show', id: @entry.id
173
+ # else
174
+ # # things didn't go so well, do something else
175
+ # end
144
176
  # end
145
- # end
146
177
  #
147
- # In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method, which is then executed.
148
- # Note that this is an external HTTP-level redirection which will cause the browser to make a second request (a GET to the show action),
149
- # and not some internal re-routing which calls both "create" and then "show" within one request.
178
+ # In this case, after saving our new entry to the database, the user is
179
+ # redirected to the `show` method, which is then executed. Note that this is an
180
+ # external HTTP-level redirection which will cause the browser to make a second
181
+ # request (a GET to the show action), and not some internal re-routing which
182
+ # calls both "create" and then "show" within one request.
150
183
  #
151
- # Learn more about <tt>redirect_to</tt> and what options you have in ActionController::Redirecting.
184
+ # Learn more about `redirect_to` and what options you have in
185
+ # ActionController::Redirecting.
152
186
  #
153
- # == Calling multiple redirects or renders
187
+ # ## Calling multiple redirects or renders
154
188
  #
155
- # An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError:
189
+ # An action may perform only a single render or a single redirect. Attempting to
190
+ # do either again will result in a DoubleRenderError:
156
191
  #
157
- # def do_something
158
- # redirect_to action: "elsewhere"
159
- # render action: "overthere" # raises DoubleRenderError
160
- # end
192
+ # def do_something
193
+ # redirect_to action: "elsewhere"
194
+ # render action: "overthere" # raises DoubleRenderError
195
+ # end
161
196
  #
162
- # If you need to redirect on the condition of something, then be sure to add "and return" to halt execution.
197
+ # If you need to redirect on the condition of something, then be sure to add
198
+ # "return" to halt execution.
163
199
  #
164
- # def do_something
165
- # redirect_to(action: "elsewhere") and return if monkeys.nil?
166
- # render action: "overthere" # won't be called if monkeys is nil
167
- # end
200
+ # def do_something
201
+ # if monkeys.nil?
202
+ # redirect_to(action: "elsewhere")
203
+ # return
204
+ # end
205
+ # render action: "overthere" # won't be called if monkeys is nil
206
+ # end
168
207
  #
169
208
  class Base < Metal
170
209
  abstract!
@@ -172,15 +211,15 @@ module ActionController
172
211
  # Shortcut helper that returns all the modules included in
173
212
  # ActionController::Base except the ones passed as arguments:
174
213
  #
175
- # class MyBaseController < ActionController::Metal
176
- # ActionController::Base.without_modules(:ParamsWrapper, :Streaming).each do |left|
177
- # include left
214
+ # class MyBaseController < ActionController::Metal
215
+ # ActionController::Base.without_modules(:ParamsWrapper, :Streaming).each do |left|
216
+ # include left
217
+ # end
178
218
  # end
179
- # end
180
219
  #
181
- # This gives better control over what you want to exclude and makes it
182
- # easier to create a bare controller class, instead of listing the modules
183
- # required manually.
220
+ # This gives better control over what you want to exclude and makes it easier to
221
+ # create a bare controller class, instead of listing the modules required
222
+ # manually.
184
223
  def self.without_modules(*modules)
185
224
  modules = modules.map do |m|
186
225
  m.is_a?(Symbol) ? ActionController.const_get(m) : m
@@ -193,7 +232,6 @@ module ActionController
193
232
  AbstractController::Rendering,
194
233
  AbstractController::Translation,
195
234
  AbstractController::AssetPaths,
196
-
197
235
  Helpers,
198
236
  UrlFor,
199
237
  Redirecting,
@@ -214,6 +252,8 @@ module ActionController
214
252
  RequestForgeryProtection,
215
253
  ContentSecurityPolicy,
216
254
  PermissionsPolicy,
255
+ RateLimiting,
256
+ AllowBrowser,
217
257
  Streaming,
218
258
  DataStreaming,
219
259
  HttpAuthentication::Basic::ControllerMethods,
@@ -221,32 +261,65 @@ module ActionController
221
261
  HttpAuthentication::Token::ControllerMethods,
222
262
  DefaultHeaders,
223
263
  Logging,
224
-
225
- # Before callbacks should also be executed as early as possible, so
226
- # also include them at the bottom.
227
264
  AbstractController::Callbacks,
228
-
229
- # Append rescue at the bottom to wrap as much as possible.
230
265
  Rescue,
231
-
232
- # Add instrumentations hooks at the bottom, to ensure they instrument
233
- # all the methods properly.
234
266
  Instrumentation,
235
-
236
- # Params wrapper should come before instrumentation so they are
237
- # properly showed in logs
238
267
  ParamsWrapper
239
268
  ]
240
269
 
241
- MODULES.each do |mod|
242
- include mod
243
- end
270
+ # Note: Documenting these severely degrades the performance of rdoc
271
+ # :stopdoc:
272
+ include AbstractController::Rendering
273
+ include AbstractController::Translation
274
+ include AbstractController::AssetPaths
275
+ include Helpers
276
+ include UrlFor
277
+ include Redirecting
278
+ include ActionView::Layouts
279
+ include Rendering
280
+ include Renderers::All
281
+ include ConditionalGet
282
+ include EtagWithTemplateDigest
283
+ include EtagWithFlash
284
+ include Caching
285
+ include MimeResponds
286
+ include ImplicitRender
287
+ include StrongParameters
288
+ include ParameterEncoding
289
+ include Cookies
290
+ include Flash
291
+ include FormBuilder
292
+ include RequestForgeryProtection
293
+ include ContentSecurityPolicy
294
+ include PermissionsPolicy
295
+ include RateLimiting
296
+ include AllowBrowser
297
+ include Streaming
298
+ include DataStreaming
299
+ include HttpAuthentication::Basic::ControllerMethods
300
+ include HttpAuthentication::Digest::ControllerMethods
301
+ include HttpAuthentication::Token::ControllerMethods
302
+ include DefaultHeaders
303
+ include Logging
304
+ # Before callbacks should also be executed as early as possible, so also include
305
+ # them at the bottom.
306
+ include AbstractController::Callbacks
307
+ # Append rescue at the bottom to wrap as much as possible.
308
+ include Rescue
309
+ # Add instrumentations hooks at the bottom, to ensure they instrument all the
310
+ # methods properly.
311
+ include Instrumentation
312
+ # Params wrapper should come before instrumentation so they are properly showed
313
+ # in logs
314
+ include ParamsWrapper
315
+ # :startdoc:
244
316
  setup_renderer!
245
317
 
246
318
  # Define some internal variables that should not be propagated to the view.
247
319
  PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + %i(
248
320
  @_params @_response @_request @_config @_url_options @_action_has_layout @_view_context_class
249
321
  @_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
322
+ @_marked_for_same_origin_verification @_rendered_format
250
323
  )
251
324
 
252
325
  def _protected_ivars
@@ -1,28 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
- # = Action Controller \Caching
5
- #
6
- # \Caching is a cheap way of speeding up slow applications by keeping the result of
7
- # calculations, renderings, and database calls around for subsequent requests.
6
+ # # Action Controller Caching
8
7
  #
9
- # You can read more about each approach by clicking the modules below.
8
+ # Caching is a cheap way of speeding up slow applications by keeping the result
9
+ # of calculations, renderings, and database calls around for subsequent
10
+ # requests.
10
11
  #
11
12
  # Note: To turn off all caching provided by Action Controller, set
12
- # config.action_controller.perform_caching = false
13
13
  #
14
- # == \Caching stores
14
+ # config.action_controller.perform_caching = false
15
+ #
16
+ # ## Caching stores
15
17
  #
16
- # All the caching stores from ActiveSupport::Cache are available to be used as backends
17
- # for Action Controller caching.
18
+ # All the caching stores from ActiveSupport::Cache are available to be used as
19
+ # backends for Action Controller caching.
18
20
  #
19
21
  # Configuration examples (FileStore is the default):
20
22
  #
21
- # config.action_controller.cache_store = :memory_store
22
- # config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
23
- # config.action_controller.cache_store = :mem_cache_store, 'localhost'
24
- # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
25
- # config.action_controller.cache_store = MyOwnStore.new('parameter')
23
+ # config.action_controller.cache_store = :memory_store
24
+ # config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
25
+ # config.action_controller.cache_store = :mem_cache_store, 'localhost'
26
+ # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
27
+ # config.action_controller.cache_store = MyOwnStore.new('parameter')
26
28
  module Caching
27
29
  extend ActiveSupport::Concern
28
30
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
6
  def self.deprecator # :nodoc:
5
7
  AbstractController.deprecator
@@ -1,31 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
- # = Action Controller Form Builder
6
+ # # Action Controller Form Builder
5
7
  #
6
- # Override the default form builder for all views rendered by this
7
- # controller and any of its descendants. Accepts a subclass of
8
+ # Override the default form builder for all views rendered by this controller
9
+ # and any of its descendants. Accepts a subclass of
8
10
  # ActionView::Helpers::FormBuilder.
9
11
  #
10
12
  # For example, given a form builder:
11
13
  #
12
- # class AdminFormBuilder < ActionView::Helpers::FormBuilder
13
- # def special_field(name)
14
+ # class AdminFormBuilder < ActionView::Helpers::FormBuilder
15
+ # def special_field(name)
16
+ # end
14
17
  # end
15
- # end
16
18
  #
17
19
  # The controller specifies a form builder as its default:
18
20
  #
19
- # class AdminAreaController < ApplicationController
20
- # default_form_builder AdminFormBuilder
21
- # end
21
+ # class AdminAreaController < ApplicationController
22
+ # default_form_builder AdminFormBuilder
23
+ # end
22
24
  #
23
- # Then in the view any form using +form_for+ will be an instance of the
24
- # specified form builder:
25
+ # Then in the view any form using `form_with` or `form_for` will be an
26
+ # instance of the specified form builder:
25
27
  #
26
- # <%= form_for(@instance) do |builder| %>
27
- # <%= builder.special_field(:name) %>
28
- # <% end %>
28
+ # <%= form_with(model: @instance) do |builder| %>
29
+ # <%= builder.special_field(:name) %>
30
+ # <% end %>
29
31
  module FormBuilder
30
32
  extend ActiveSupport::Concern
31
33
 
@@ -34,11 +36,12 @@ module ActionController
34
36
  end
35
37
 
36
38
  module ClassMethods
37
- # Set the form builder to be used as the default for all forms
38
- # in the views rendered by this controller and its subclasses.
39
+ # Set the form builder to be used as the default for all forms in the views
40
+ # rendered by this controller and its subclasses.
39
41
  #
40
- # ==== Parameters
41
- # * <tt>builder</tt> - Default form builder, an instance of ActionView::Helpers::FormBuilder
42
+ # #### Parameters
43
+ # * `builder` - Default form builder. Accepts a subclass of
44
+ # ActionView::Helpers::FormBuilder
42
45
  def default_form_builder(builder)
43
46
  self._default_form_builder = builder
44
47
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
- class LogSubscriber < ActiveSupport::LogSubscriber
4
+ class LogSubscriber < ActiveSupport::LogSubscriber # :nodoc:
5
5
  INTERNAL_PARAMS = %w(controller action format _method only_path)
6
6
 
7
+ class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
8
+
7
9
  def start_processing(event)
8
10
  return unless logger.info?
9
11
 
@@ -31,7 +33,7 @@ module ActionController
31
33
  status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
32
34
  end
33
35
 
34
- additions << "Allocations: #{event.allocations}"
36
+ additions << "GC: #{event.gc_time.round(1)}ms"
35
37
 
36
38
  message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" \
37
39
  " (#{additions.join(" | ")})"
@@ -47,6 +49,17 @@ module ActionController
47
49
  end
48
50
  subscribe_log_level :halted_callback, :info
49
51
 
52
+ # Manually subscribed below
53
+ def rescue_from_callback(event)
54
+ exception = event.payload[:exception]
55
+
56
+ exception_backtrace = exception.backtrace&.first
57
+ exception_backtrace = exception_backtrace&.delete_prefix("#{Rails.root}/") if defined?(Rails.root) && Rails.root
58
+
59
+ info { "rescue_from handled #{exception.class} (#{exception.message}) - #{exception_backtrace}" }
60
+ end
61
+ subscribe_log_level :rescue_from_callback, :info
62
+
50
63
  def send_file(event)
51
64
  info { "Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)" }
52
65
  end
@@ -54,6 +67,10 @@ module ActionController
54
67
 
55
68
  def redirect_to(event)
56
69
  info { "Redirected to #{event.payload[:location]}" }
70
+
71
+ if ActionDispatch.verbose_redirect_logs && (source = redirect_source_location)
72
+ info { "↳ #{source}" }
73
+ end
57
74
  end
58
75
  subscribe_log_level :redirect_to, :info
59
76
 
@@ -88,6 +105,10 @@ module ActionController
88
105
  def logger
89
106
  ActionController::Base.logger
90
107
  end
108
+
109
+ def redirect_source_location
110
+ backtrace_cleaner.first_clean_frame
111
+ end
91
112
  end
92
113
  end
93
114