actionpack 4.2.11.1 → 5.2.4.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +300 -476
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +45 -49
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +78 -15
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/callbacks.rb +47 -31
- data/lib/abstract_controller/collector.rb +8 -11
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +25 -25
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +4 -2
- data/lib/abstract_controller/rendering.rb +42 -41
- data/lib/abstract_controller/translation.rb +10 -7
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +12 -5
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/base.rb +27 -19
- data/lib/action_controller/caching.rb +14 -57
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +10 -15
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +118 -44
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +27 -46
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
- data/lib/action_controller/metal/exceptions.rb +8 -14
- data/lib/action_controller/metal/flash.rb +4 -3
- data/lib/action_controller/metal/force_ssl.rb +23 -21
- data/lib/action_controller/metal/head.rb +21 -19
- data/lib/action_controller/metal/helpers.rb +24 -14
- data/lib/action_controller/metal/http_authentication.rb +65 -58
- data/lib/action_controller/metal/implicit_render.rb +62 -8
- data/lib/action_controller/metal/instrumentation.rb +19 -21
- data/lib/action_controller/metal/live.rb +90 -106
- data/lib/action_controller/metal/mime_responds.rb +33 -46
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +61 -53
- data/lib/action_controller/metal/redirecting.rb +49 -28
- data/lib/action_controller/metal/renderers.rb +87 -44
- data/lib/action_controller/metal/rendering.rb +72 -50
- data/lib/action_controller/metal/request_forgery_protection.rb +229 -93
- data/lib/action_controller/metal/rescue.rb +9 -16
- data/lib/action_controller/metal/streaming.rb +12 -10
- data/lib/action_controller/metal/strong_parameters.rb +583 -164
- data/lib/action_controller/metal/testing.rb +2 -17
- data/lib/action_controller/metal/url_for.rb +19 -10
- data/lib/action_controller/metal.rb +98 -83
- data/lib/action_controller/railtie.rb +28 -10
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +280 -411
- data/lib/action_controller.rb +29 -21
- data/lib/action_dispatch/http/cache.rb +93 -47
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +26 -20
- data/lib/action_dispatch/http/filter_redirect.rb +10 -11
- data/lib/action_dispatch/http/headers.rb +55 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +56 -41
- data/lib/action_dispatch/http/mime_type.rb +134 -121
- data/lib/action_dispatch/http/mime_types.rb +20 -6
- data/lib/action_dispatch/http/parameter_filter.rb +25 -11
- data/lib/action_dispatch/http/parameters.rb +98 -39
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +200 -118
- data/lib/action_dispatch/http/response.rb +225 -110
- data/lib/action_dispatch/http/upload.rb +12 -6
- data/lib/action_dispatch/http/url.rb +110 -28
- data/lib/action_dispatch/journey/formatter.rb +55 -32
- data/lib/action_dispatch/journey/gtg/builder.rb +7 -5
- data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
- data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -16
- data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
- data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
- data/lib/action_dispatch/journey/nfa/simulator.rb +3 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -48
- data/lib/action_dispatch/journey/nodes/node.rb +18 -6
- data/lib/action_dispatch/journey/parser.rb +23 -22
- data/lib/action_dispatch/journey/parser.y +3 -2
- data/lib/action_dispatch/journey/parser_extras.rb +12 -4
- data/lib/action_dispatch/journey/path/pattern.rb +50 -44
- data/lib/action_dispatch/journey/route.rb +106 -28
- data/lib/action_dispatch/journey/router/utils.rb +20 -11
- data/lib/action_dispatch/journey/router.rb +35 -23
- data/lib/action_dispatch/journey/routes.rb +18 -16
- data/lib/action_dispatch/journey/scanner.rb +18 -15
- data/lib/action_dispatch/journey/visitors.rb +99 -52
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/middleware/callbacks.rb +1 -2
- data/lib/action_dispatch/middleware/cookies.rb +304 -193
- data/lib/action_dispatch/middleware/debug_exceptions.rb +152 -57
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +68 -69
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +78 -54
- data/lib/action_dispatch/middleware/public_exceptions.rb +27 -25
- data/lib/action_dispatch/middleware/reloader.rb +5 -91
- data/lib/action_dispatch/middleware/remote_ip.rb +41 -31
- data/lib/action_dispatch/middleware/request_id.rb +17 -9
- data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -25
- data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
- data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -67
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +26 -22
- data/lib/action_dispatch/middleware/ssl.rb +114 -36
- data/lib/action_dispatch/middleware/stack.rb +31 -44
- data/lib/action_dispatch/middleware/static.rb +57 -50
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -64
- data/lib/action_dispatch/railtie.rb +19 -11
- data/lib/action_dispatch/request/session.rb +106 -59
- data/lib/action_dispatch/request/utils.rb +67 -24
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +58 -67
- data/lib/action_dispatch/routing/mapper.rb +733 -447
- data/lib/action_dispatch/routing/polymorphic_routes.rb +166 -140
- data/lib/action_dispatch/routing/redirection.rb +36 -26
- data/lib/action_dispatch/routing/route_set.rb +321 -291
- data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
- data/lib/action_dispatch/routing/url_for.rb +65 -25
- data/lib/action_dispatch/routing.rb +17 -18
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions/response.rb +45 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +30 -26
- data/lib/action_dispatch/testing/assertions.rb +6 -4
- data/lib/action_dispatch/testing/integration.rb +347 -209
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +28 -22
- data/lib/action_dispatch/testing/test_request.rb +27 -34
- data/lib/action_dispatch/testing/test_response.rb +35 -7
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +4 -2
- metadata +59 -41
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -28,31 +28,30 @@ can be used outside of Rails.
|
|
28
28
|
|
29
29
|
The latest version of Action Pack can be installed with RubyGems:
|
30
30
|
|
31
|
-
|
31
|
+
$ gem install actionpack
|
32
32
|
|
33
|
-
Source code can be downloaded as part of the Rails project on GitHub
|
33
|
+
Source code can be downloaded as part of the Rails project on GitHub:
|
34
34
|
|
35
|
-
* https://github.com/rails/rails/tree/
|
35
|
+
* https://github.com/rails/rails/tree/5-2-stable/actionpack
|
36
36
|
|
37
37
|
|
38
38
|
== License
|
39
39
|
|
40
40
|
Action Pack is released under the MIT license:
|
41
41
|
|
42
|
-
*
|
42
|
+
* https://opensource.org/licenses/MIT
|
43
43
|
|
44
44
|
|
45
45
|
== Support
|
46
46
|
|
47
|
-
API documentation is at
|
47
|
+
API documentation is at:
|
48
48
|
|
49
49
|
* http://api.rubyonrails.org
|
50
50
|
|
51
|
-
Bug reports
|
51
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
52
52
|
|
53
53
|
* https://github.com/rails/rails/issues
|
54
54
|
|
55
55
|
Feature requests should be discussed on the rails-core mailing list here:
|
56
56
|
|
57
57
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
58
|
-
|
@@ -1,30 +1,36 @@
|
|
1
|
-
|
2
|
-
require 'set'
|
3
|
-
require 'active_support/configurable'
|
4
|
-
require 'active_support/descendants_tracker'
|
5
|
-
require 'active_support/core_ext/module/anonymous'
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
require "abstract_controller/error"
|
4
|
+
require "active_support/configurable"
|
5
|
+
require "active_support/descendants_tracker"
|
6
|
+
require "active_support/core_ext/module/anonymous"
|
7
|
+
require "active_support/core_ext/module/attr_internal"
|
10
8
|
|
9
|
+
module AbstractController
|
11
10
|
# Raised when a non-existing controller action is triggered.
|
12
11
|
class ActionNotFound < StandardError
|
13
12
|
end
|
14
13
|
|
15
|
-
#
|
14
|
+
# AbstractController::Base is a low-level API. Nobody should be
|
16
15
|
# using it directly, and subclasses (like ActionController::Base) are
|
17
16
|
# expected to provide their own +render+ method, since rendering means
|
18
17
|
# different things depending on the context.
|
19
18
|
class Base
|
19
|
+
##
|
20
|
+
# Returns the body of the HTTP response sent by the controller.
|
20
21
|
attr_internal :response_body
|
22
|
+
|
23
|
+
##
|
24
|
+
# Returns the name of the action this controller is processing.
|
21
25
|
attr_internal :action_name
|
26
|
+
|
27
|
+
##
|
28
|
+
# Returns the formats that can be processed by the controller.
|
22
29
|
attr_internal :formats
|
23
30
|
|
24
31
|
include ActiveSupport::Configurable
|
25
32
|
extend ActiveSupport::DescendantsTracker
|
26
33
|
|
27
|
-
undef_method :not_implemented
|
28
34
|
class << self
|
29
35
|
attr_reader :abstract
|
30
36
|
alias_method :abstract?, :abstract
|
@@ -49,7 +55,7 @@ module AbstractController
|
|
49
55
|
# instance methods on that abstract class. Public instance methods of
|
50
56
|
# a controller would normally be considered action methods, so methods
|
51
57
|
# declared on abstract classes are being removed.
|
52
|
-
# (ActionController::Metal and ActionController::Base are defined as abstract)
|
58
|
+
# (<tt>ActionController::Metal</tt> and ActionController::Base are defined as abstract)
|
53
59
|
def internal_methods
|
54
60
|
controller = self
|
55
61
|
|
@@ -57,21 +63,11 @@ module AbstractController
|
|
57
63
|
controller.public_instance_methods(true)
|
58
64
|
end
|
59
65
|
|
60
|
-
# The list of hidden actions. Defaults to an empty array.
|
61
|
-
# This can be modified by other modules or subclasses
|
62
|
-
# to specify particular actions as hidden.
|
63
|
-
#
|
64
|
-
# ==== Returns
|
65
|
-
# * <tt>Array</tt> - An array of method names that should not be considered actions.
|
66
|
-
def hidden_actions
|
67
|
-
[]
|
68
|
-
end
|
69
|
-
|
70
66
|
# A list of method names that should be considered actions. This
|
71
67
|
# includes all public instance methods on a controller, less
|
72
|
-
# any internal methods (see
|
68
|
+
# any internal methods (see internal_methods), adding back in
|
73
69
|
# any methods that are internal, but still exist on the class
|
74
|
-
# itself.
|
70
|
+
# itself.
|
75
71
|
#
|
76
72
|
# ==== Returns
|
77
73
|
# * <tt>Set</tt> - A set of all methods that should be considered actions.
|
@@ -82,30 +78,31 @@ module AbstractController
|
|
82
78
|
# Except for public instance methods of Base and its ancestors
|
83
79
|
internal_methods +
|
84
80
|
# Be sure to include shadowed public instance methods of this class
|
85
|
-
public_instance_methods(false)).uniq.map
|
86
|
-
# And always exclude explicitly hidden actions
|
87
|
-
hidden_actions.to_a
|
81
|
+
public_instance_methods(false)).uniq.map(&:to_s)
|
88
82
|
|
89
|
-
|
90
|
-
Set.new(methods.reject { |method| method =~ /_one_time_conditions/ })
|
83
|
+
methods.to_set
|
91
84
|
end
|
92
85
|
end
|
93
86
|
|
94
|
-
# action_methods are cached and there is sometimes need to refresh
|
95
|
-
# them. clear_action_methods! allows you to do that, so next time
|
96
|
-
# you run action_methods, they will be recalculated
|
87
|
+
# action_methods are cached and there is sometimes a need to refresh
|
88
|
+
# them. ::clear_action_methods! allows you to do that, so next time
|
89
|
+
# you run action_methods, they will be recalculated.
|
97
90
|
def clear_action_methods!
|
98
91
|
@action_methods = nil
|
99
92
|
end
|
100
93
|
|
101
94
|
# Returns the full controller name, underscored, without the ending Controller.
|
102
|
-
#
|
103
|
-
#
|
95
|
+
#
|
96
|
+
# class MyApp::MyPostsController < AbstractController::Base
|
97
|
+
#
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# MyApp::MyPostsController.controller_path # => "my_app/my_posts"
|
104
101
|
#
|
105
102
|
# ==== Returns
|
106
103
|
# * <tt>String</tt>
|
107
104
|
def controller_path
|
108
|
-
@controller_path ||= name.sub(/Controller$/,
|
105
|
+
@controller_path ||= name.sub(/Controller$/, "".freeze).underscore unless anonymous?
|
109
106
|
end
|
110
107
|
|
111
108
|
# Refresh the cached action_methods when a new action_method is added.
|
@@ -137,12 +134,12 @@ module AbstractController
|
|
137
134
|
process_action(action_name, *args)
|
138
135
|
end
|
139
136
|
|
140
|
-
# Delegates to the class'
|
137
|
+
# Delegates to the class' ::controller_path
|
141
138
|
def controller_path
|
142
139
|
self.class.controller_path
|
143
140
|
end
|
144
141
|
|
145
|
-
# Delegates to the class'
|
142
|
+
# Delegates to the class' ::action_methods
|
146
143
|
def action_methods
|
147
144
|
self.class.action_methods
|
148
145
|
end
|
@@ -157,11 +154,15 @@ module AbstractController
|
|
157
154
|
#
|
158
155
|
# ==== Parameters
|
159
156
|
# * <tt>action_name</tt> - The name of an action to be tested
|
160
|
-
#
|
161
|
-
# ==== Returns
|
162
|
-
# * <tt>TrueClass</tt>, <tt>FalseClass</tt>
|
163
157
|
def available_action?(action_name)
|
164
|
-
_find_action_name(action_name)
|
158
|
+
_find_action_name(action_name)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Tests if a response body is set. Used to determine if the
|
162
|
+
# +process_action+ callback needs to be terminated in
|
163
|
+
# +AbstractController::Callbacks+.
|
164
|
+
def performed?
|
165
|
+
response_body
|
165
166
|
end
|
166
167
|
|
167
168
|
# Returns true if the given controller is capable of rendering
|
@@ -179,11 +180,6 @@ module AbstractController
|
|
179
180
|
#
|
180
181
|
# ==== Parameters
|
181
182
|
# * <tt>name</tt> - The name of an action to be tested
|
182
|
-
#
|
183
|
-
# ==== Returns
|
184
|
-
# * <tt>TrueClass</tt>, <tt>FalseClass</tt>
|
185
|
-
#
|
186
|
-
# :api: private
|
187
183
|
def action_method?(name)
|
188
184
|
self.class.action_methods.include?(name)
|
189
185
|
end
|
@@ -225,7 +221,7 @@ module AbstractController
|
|
225
221
|
# ==== Returns
|
226
222
|
# * <tt>string</tt> - The name of the method that handles the action
|
227
223
|
# * false - No valid method name could be found.
|
228
|
-
# Raise AbstractController::ActionNotFound
|
224
|
+
# Raise +AbstractController::ActionNotFound+.
|
229
225
|
def _find_action_name(action_name)
|
230
226
|
_valid_action_name?(action_name) && method_for_action(action_name)
|
231
227
|
end
|
@@ -241,11 +237,11 @@ module AbstractController
|
|
241
237
|
# with a template matching the action name is considered to exist.
|
242
238
|
#
|
243
239
|
# If you override this method to handle additional cases, you may
|
244
|
-
# also provide a method (like _handle_method_missing) to handle
|
240
|
+
# also provide a method (like +_handle_method_missing+) to handle
|
245
241
|
# the case.
|
246
242
|
#
|
247
|
-
# If none of these conditions are true, and method_for_action
|
248
|
-
# returns nil
|
243
|
+
# If none of these conditions are true, and +method_for_action+
|
244
|
+
# returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised.
|
249
245
|
#
|
250
246
|
# ==== Parameters
|
251
247
|
# * <tt>action_name</tt> - An action name to find a method name for
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AbstractController
|
2
4
|
module Caching
|
3
5
|
# Fragment caching is used for caching various blocks within
|
4
6
|
# views without caching the entire action as a whole. This is
|
@@ -14,12 +16,79 @@ module ActionController
|
|
14
16
|
#
|
15
17
|
# expire_fragment('name_of_cache')
|
16
18
|
module Fragments
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
if respond_to?(:class_attribute)
|
23
|
+
class_attribute :fragment_cache_keys
|
24
|
+
else
|
25
|
+
mattr_writer :fragment_cache_keys
|
26
|
+
end
|
27
|
+
|
28
|
+
self.fragment_cache_keys = []
|
29
|
+
|
30
|
+
if respond_to?(:helper_method)
|
31
|
+
helper_method :fragment_cache_key
|
32
|
+
helper_method :combined_fragment_cache_key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
# Allows you to specify controller-wide key prefixes for
|
38
|
+
# cache fragments. Pass either a constant +value+, or a block
|
39
|
+
# which computes a value each time a cache key is generated.
|
40
|
+
#
|
41
|
+
# For example, you may want to prefix all fragment cache keys
|
42
|
+
# with a global version identifier, so you can easily
|
43
|
+
# invalidate all caches.
|
44
|
+
#
|
45
|
+
# class ApplicationController
|
46
|
+
# fragment_cache_key "v1"
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# When it's time to invalidate all fragments, simply change
|
50
|
+
# the string constant. Or, progressively roll out the cache
|
51
|
+
# invalidation using a computed value:
|
52
|
+
#
|
53
|
+
# class ApplicationController
|
54
|
+
# fragment_cache_key do
|
55
|
+
# @account.id.odd? ? "v1" : "v2"
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
def fragment_cache_key(value = nil, &key)
|
59
|
+
self.fragment_cache_keys += [key || -> { value }]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
17
63
|
# Given a key (as described in +expire_fragment+), returns
|
18
64
|
# a key suitable for use in reading, writing, or expiring a
|
19
|
-
# cached fragment. All keys
|
20
|
-
#
|
65
|
+
# cached fragment. All keys begin with <tt>views/</tt>,
|
66
|
+
# followed by any controller-wide key prefix values, ending
|
67
|
+
# with the specified +key+ value. The key is expanded using
|
68
|
+
# ActiveSupport::Cache.expand_cache_key.
|
21
69
|
def fragment_cache_key(key)
|
22
|
-
ActiveSupport::
|
70
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
71
|
+
Calling fragment_cache_key directly is deprecated and will be removed in Rails 6.0.
|
72
|
+
All fragment accessors now use the combined_fragment_cache_key method that retains the key as an array,
|
73
|
+
such that the caching stores can interrogate the parts for cache versions used in
|
74
|
+
recyclable cache keys.
|
75
|
+
MSG
|
76
|
+
|
77
|
+
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
|
78
|
+
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
|
79
|
+
ActiveSupport::Cache.expand_cache_key([*head, *tail], :views)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Given a key (as described in +expire_fragment+), returns
|
83
|
+
# a key array suitable for use in reading, writing, or expiring a
|
84
|
+
# cached fragment. All keys begin with <tt>:views</tt>,
|
85
|
+
# followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set,
|
86
|
+
# followed by any controller-wide key prefix values, ending
|
87
|
+
# with the specified +key+ value.
|
88
|
+
def combined_fragment_cache_key(key)
|
89
|
+
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
|
90
|
+
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
|
91
|
+
[ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact
|
23
92
|
end
|
24
93
|
|
25
94
|
# Writes +content+ to the location signified by
|
@@ -27,7 +96,7 @@ module ActionController
|
|
27
96
|
def write_fragment(key, content, options = nil)
|
28
97
|
return content unless cache_configured?
|
29
98
|
|
30
|
-
key =
|
99
|
+
key = combined_fragment_cache_key(key)
|
31
100
|
instrument_fragment_cache :write_fragment, key do
|
32
101
|
content = content.to_str
|
33
102
|
cache_store.write(key, content, options)
|
@@ -40,7 +109,7 @@ module ActionController
|
|
40
109
|
def read_fragment(key, options = nil)
|
41
110
|
return unless cache_configured?
|
42
111
|
|
43
|
-
key =
|
112
|
+
key = combined_fragment_cache_key(key)
|
44
113
|
instrument_fragment_cache :read_fragment, key do
|
45
114
|
result = cache_store.read(key, options)
|
46
115
|
result.respond_to?(:html_safe) ? result.html_safe : result
|
@@ -51,7 +120,7 @@ module ActionController
|
|
51
120
|
# +key+ exists (see +expire_fragment+ for acceptable formats).
|
52
121
|
def fragment_exist?(key, options = nil)
|
53
122
|
return unless cache_configured?
|
54
|
-
key =
|
123
|
+
key = combined_fragment_cache_key(key)
|
55
124
|
|
56
125
|
instrument_fragment_cache :exist_fragment?, key do
|
57
126
|
cache_store.exist?(key, options)
|
@@ -78,7 +147,7 @@ module ActionController
|
|
78
147
|
# method (or <tt>delete_matched</tt>, for Regexp keys).
|
79
148
|
def expire_fragment(key, options = nil)
|
80
149
|
return unless cache_configured?
|
81
|
-
key =
|
150
|
+
key = combined_fragment_cache_key(key) unless key.is_a?(Regexp)
|
82
151
|
|
83
152
|
instrument_fragment_cache :expire_fragment, key do
|
84
153
|
if key.is_a?(Regexp)
|
@@ -90,13 +159,7 @@ module ActionController
|
|
90
159
|
end
|
91
160
|
|
92
161
|
def instrument_fragment_cache(name, key) # :nodoc:
|
93
|
-
|
94
|
-
controller: controller_name,
|
95
|
-
action: action_name,
|
96
|
-
key: key
|
97
|
-
}
|
98
|
-
|
99
|
-
ActiveSupport::Notifications.instrument("#{name}.action_controller", payload) { yield }
|
162
|
+
ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key)) { yield }
|
100
163
|
end
|
101
164
|
end
|
102
165
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AbstractController
|
4
|
+
module Caching
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
eager_autoload do
|
9
|
+
autoload :Fragments
|
10
|
+
end
|
11
|
+
|
12
|
+
module ConfigMethods
|
13
|
+
def cache_store
|
14
|
+
config.cache_store
|
15
|
+
end
|
16
|
+
|
17
|
+
def cache_store=(store)
|
18
|
+
config.cache_store = ActiveSupport::Cache.lookup_store(store)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def cache_configured?
|
23
|
+
perform_caching && cache_store
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
include ConfigMethods
|
28
|
+
include AbstractController::Caching::Fragments
|
29
|
+
|
30
|
+
included do
|
31
|
+
extend ConfigMethods
|
32
|
+
|
33
|
+
config_accessor :default_static_extension
|
34
|
+
self.default_static_extension ||= ".html"
|
35
|
+
|
36
|
+
config_accessor :perform_caching
|
37
|
+
self.perform_caching = true if perform_caching.nil?
|
38
|
+
|
39
|
+
config_accessor :enable_fragment_cache_logging
|
40
|
+
self.enable_fragment_cache_logging = false
|
41
|
+
|
42
|
+
class_attribute :_view_cache_dependencies, default: []
|
43
|
+
helper_method :view_cache_dependencies if respond_to?(:helper_method)
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
def view_cache_dependency(&dependency)
|
48
|
+
self._view_cache_dependencies += [dependency]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def view_cache_dependencies
|
53
|
+
self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
# Convenience accessor.
|
58
|
+
def cache(key, options = {}, &block) # :doc:
|
59
|
+
if cache_configured?
|
60
|
+
cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block)
|
61
|
+
else
|
62
|
+
yield
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,4 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AbstractController
|
4
|
+
# = Abstract Controller Callbacks
|
5
|
+
#
|
6
|
+
# Abstract Controller provides hooks during the life cycle of a controller action.
|
7
|
+
# Callbacks allow you to trigger logic during this cycle. Available callbacks are:
|
8
|
+
#
|
9
|
+
# * <tt>after_action</tt>
|
10
|
+
# * <tt>append_after_action</tt>
|
11
|
+
# * <tt>append_around_action</tt>
|
12
|
+
# * <tt>append_before_action</tt>
|
13
|
+
# * <tt>around_action</tt>
|
14
|
+
# * <tt>before_action</tt>
|
15
|
+
# * <tt>prepend_after_action</tt>
|
16
|
+
# * <tt>prepend_around_action</tt>
|
17
|
+
# * <tt>prepend_before_action</tt>
|
18
|
+
# * <tt>skip_after_action</tt>
|
19
|
+
# * <tt>skip_around_action</tt>
|
20
|
+
# * <tt>skip_before_action</tt>
|
21
|
+
#
|
22
|
+
# NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
|
23
|
+
#
|
2
24
|
module Callbacks
|
3
25
|
extend ActiveSupport::Concern
|
4
26
|
|
@@ -9,12 +31,12 @@ module AbstractController
|
|
9
31
|
|
10
32
|
included do
|
11
33
|
define_callbacks :process_action,
|
12
|
-
terminator: ->(controller,
|
34
|
+
terminator: ->(controller, result_lambda) { result_lambda.call; controller.performed? },
|
13
35
|
skip_after_callbacks_if_terminated: true
|
14
36
|
end
|
15
37
|
|
16
|
-
# Override AbstractController::Base
|
17
|
-
# process_action callbacks around the normal behavior.
|
38
|
+
# Override <tt>AbstractController::Base#process_action</tt> to run the
|
39
|
+
# <tt>process_action</tt> callbacks around the normal behavior.
|
18
40
|
def process_action(*args)
|
19
41
|
run_callbacks(:process_action) do
|
20
42
|
super
|
@@ -22,14 +44,25 @@ module AbstractController
|
|
22
44
|
end
|
23
45
|
|
24
46
|
module ClassMethods
|
25
|
-
# If
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
47
|
+
# If +:only+ or +:except+ are used, convert the options into the
|
48
|
+
# +:if+ and +:unless+ options of ActiveSupport::Callbacks.
|
49
|
+
#
|
50
|
+
# The basic idea is that <tt>:only => :index</tt> gets converted to
|
51
|
+
# <tt>:if => proc {|c| c.action_name == "index" }</tt>.
|
52
|
+
#
|
53
|
+
# Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
|
54
|
+
# are used together.
|
55
|
+
#
|
56
|
+
# only: :index, if: -> { true } # the :if option will be ignored.
|
57
|
+
#
|
58
|
+
# Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
|
59
|
+
# are used together.
|
60
|
+
#
|
61
|
+
# except: :index, if: -> { true } # the :except option will be ignored.
|
29
62
|
#
|
30
63
|
# ==== Options
|
31
|
-
# * <tt>only</tt> - The callback should be run only for this action
|
32
|
-
# * <tt>except</tt> - The callback should be run for all actions except this action
|
64
|
+
# * <tt>only</tt> - The callback should be run only for this action.
|
65
|
+
# * <tt>except</tt> - The callback should be run for all actions except this action.
|
33
66
|
def _normalize_callback_options(options)
|
34
67
|
_normalize_callback_option(options, :only, :if)
|
35
68
|
_normalize_callback_option(options, :except, :unless)
|
@@ -37,25 +70,12 @@ module AbstractController
|
|
37
70
|
|
38
71
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
39
72
|
if from = options[from]
|
40
|
-
|
73
|
+
_from = Array(from).map(&:to_s).to_set
|
74
|
+
from = proc { |c| _from.include? c.action_name }
|
41
75
|
options[to] = Array(options[to]).unshift(from)
|
42
76
|
end
|
43
77
|
end
|
44
78
|
|
45
|
-
# Skip before, after, and around action callbacks matching any of the names.
|
46
|
-
#
|
47
|
-
# ==== Parameters
|
48
|
-
# * <tt>names</tt> - A list of valid names that could be used for
|
49
|
-
# callbacks. Note that skipping uses Ruby equality, so it's
|
50
|
-
# impossible to skip a callback defined using an anonymous proc
|
51
|
-
# using #skip_action_callback
|
52
|
-
def skip_action_callback(*names)
|
53
|
-
skip_before_action(*names)
|
54
|
-
skip_after_action(*names)
|
55
|
-
skip_around_action(*names)
|
56
|
-
end
|
57
|
-
alias_method :skip_filter, :skip_action_callback
|
58
|
-
|
59
79
|
# Take callback names and an optional callback proc, normalize them,
|
60
80
|
# then call the block with each callback. This allows us to abstract
|
61
81
|
# the normalization across several methods that use it.
|
@@ -66,8 +86,8 @@ module AbstractController
|
|
66
86
|
# * <tt>block</tt> - A proc that should be added to the callbacks.
|
67
87
|
#
|
68
88
|
# ==== Block Parameters
|
69
|
-
# * <tt>name</tt> - The callback to be added
|
70
|
-
# * <tt>options</tt> - A hash of options to be used when adding the callback
|
89
|
+
# * <tt>name</tt> - The callback to be added.
|
90
|
+
# * <tt>options</tt> - A hash of options to be used when adding the callback.
|
71
91
|
def _insert_callbacks(callbacks, block = nil)
|
72
92
|
options = callbacks.extract_options!
|
73
93
|
_normalize_callback_options(options)
|
@@ -169,14 +189,12 @@ module AbstractController
|
|
169
189
|
set_callback(:process_action, callback, name, options)
|
170
190
|
end
|
171
191
|
end
|
172
|
-
alias_method :"#{callback}_filter", :"#{callback}_action"
|
173
192
|
|
174
193
|
define_method "prepend_#{callback}_action" do |*names, &blk|
|
175
194
|
_insert_callbacks(names, blk) do |name, options|
|
176
|
-
set_callback(:process_action, callback, name, options.merge(:
|
195
|
+
set_callback(:process_action, callback, name, options.merge(prepend: true))
|
177
196
|
end
|
178
197
|
end
|
179
|
-
alias_method :"prepend_#{callback}_filter", :"prepend_#{callback}_action"
|
180
198
|
|
181
199
|
# Skip a before, after or around callback. See _insert_callbacks
|
182
200
|
# for details on the allowed parameters.
|
@@ -185,11 +203,9 @@ module AbstractController
|
|
185
203
|
skip_callback(:process_action, callback, name, options)
|
186
204
|
end
|
187
205
|
end
|
188
|
-
alias_method :"skip_#{callback}_filter", :"skip_#{callback}_action"
|
189
206
|
|
190
207
|
# *_action is the same as append_*_action
|
191
208
|
alias_method :"append_#{callback}_action", :"#{callback}_action"
|
192
|
-
alias_method :"append_#{callback}_filter", :"#{callback}_action"
|
193
209
|
end
|
194
210
|
end
|
195
211
|
end
|
@@ -1,14 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch/http/mime_type"
|
2
4
|
|
3
5
|
module AbstractController
|
4
6
|
module Collector
|
5
7
|
def self.generate_method_for_mime(mime)
|
6
8
|
sym = mime.is_a?(Symbol) ? mime : mime.to_sym
|
7
|
-
const = sym.upcase
|
8
9
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
9
|
-
def #{sym}(*args, &block)
|
10
|
-
custom(Mime
|
11
|
-
end
|
10
|
+
def #{sym}(*args, &block)
|
11
|
+
custom(Mime[:#{sym}], *args, &block)
|
12
|
+
end
|
12
13
|
RUBY
|
13
14
|
end
|
14
15
|
|
@@ -17,15 +18,13 @@ module AbstractController
|
|
17
18
|
end
|
18
19
|
|
19
20
|
Mime::Type.register_callback do |mime|
|
20
|
-
generate_method_for_mime(mime) unless
|
21
|
+
generate_method_for_mime(mime) unless instance_methods.include?(mime.to_sym)
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
+
private
|
24
25
|
|
25
26
|
def method_missing(symbol, &block)
|
26
|
-
|
27
|
-
|
28
|
-
unless Mime.const_defined?(const_name)
|
27
|
+
unless mime_constant = Mime[symbol]
|
29
28
|
raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
|
30
29
|
"http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
|
31
30
|
"If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
|
@@ -33,8 +32,6 @@ module AbstractController
|
|
33
32
|
"format.html { |html| html.tablet { ... } }"
|
34
33
|
end
|
35
34
|
|
36
|
-
mime_constant = Mime.const_get(const_name)
|
37
|
-
|
38
35
|
if Mime::SET.include?(mime_constant)
|
39
36
|
AbstractController::Collector.generate_method_for_mime(mime_constant)
|
40
37
|
send(symbol, &block)
|