actionpack 4.2.10 → 7.2.0.rc1
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.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- 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/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- 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
@@ -1,119 +1,209 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/dependencies"
|
6
|
+
require "active_support/core_ext/name_error"
|
2
7
|
|
3
8
|
module AbstractController
|
4
9
|
module Helpers
|
5
10
|
extend ActiveSupport::Concern
|
6
11
|
|
7
12
|
included do
|
8
|
-
class_attribute :
|
9
|
-
self._helpers = Module.new
|
13
|
+
class_attribute :_helper_methods, default: Array.new
|
10
14
|
|
11
|
-
|
12
|
-
|
15
|
+
# This is here so that it is always higher in the inheritance chain than the
|
16
|
+
# definition in lib/action_view/rendering.rb
|
17
|
+
redefine_singleton_method(:_helpers) do
|
18
|
+
if @_helpers ||= nil
|
19
|
+
@_helpers
|
20
|
+
else
|
21
|
+
superclass._helpers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
self._helpers = define_helpers_module(self)
|
13
26
|
end
|
14
27
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@path = "helpers/#{path}.rb"
|
19
|
-
set_backtrace error.backtrace
|
28
|
+
def _helpers
|
29
|
+
self.class._helpers
|
30
|
+
end
|
20
31
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
32
|
+
module Resolution # :nodoc:
|
33
|
+
def modules_for_helpers(modules_or_helper_prefixes)
|
34
|
+
modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
|
35
|
+
case module_or_helper_prefix
|
36
|
+
when Module
|
37
|
+
module_or_helper_prefix
|
38
|
+
when String, Symbol
|
39
|
+
helper_prefix = module_or_helper_prefix.to_s
|
40
|
+
helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
|
41
|
+
"#{helper_prefix}Helper".constantize
|
42
|
+
else
|
43
|
+
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_helpers_from_path(path)
|
49
|
+
helpers = Array(path).flat_map do |_path|
|
50
|
+
names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
|
51
|
+
names.sort!
|
25
52
|
end
|
53
|
+
helpers.uniq!
|
54
|
+
helpers
|
55
|
+
end
|
56
|
+
|
57
|
+
def helper_modules_from_paths(paths)
|
58
|
+
modules_for_helpers(all_helpers_from_path(paths))
|
26
59
|
end
|
27
60
|
end
|
28
61
|
|
62
|
+
extend Resolution
|
63
|
+
|
29
64
|
module ClassMethods
|
30
|
-
# When a class is inherited, wrap its helper module in a new module.
|
31
|
-
#
|
32
|
-
#
|
65
|
+
# When a class is inherited, wrap its helper module in a new module. This
|
66
|
+
# ensures that the parent class's module can be changed independently of the
|
67
|
+
# child class's.
|
33
68
|
def inherited(klass)
|
34
|
-
|
35
|
-
klass._helpers =
|
69
|
+
# Inherited from parent by default
|
70
|
+
klass._helpers = nil
|
71
|
+
|
36
72
|
klass.class_eval { default_helper_module! } unless klass.anonymous?
|
37
73
|
super
|
38
74
|
end
|
39
75
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
76
|
+
attr_writer :_helpers
|
77
|
+
|
78
|
+
include Resolution
|
79
|
+
|
80
|
+
##
|
81
|
+
# :method: modules_for_helpers
|
82
|
+
# :call-seq: modules_for_helpers(modules_or_helper_prefixes)
|
44
83
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
84
|
+
# Given an array of values like the ones accepted by `helper`, this method
|
85
|
+
# returns an array with the corresponding modules, in the same order.
|
86
|
+
#
|
87
|
+
# ActionController::Base.modules_for_helpers(["application", "chart", "rubygems"])
|
88
|
+
# # => [ApplicationHelper, ChartHelper, RubygemsHelper]
|
89
|
+
#
|
90
|
+
#--
|
91
|
+
# Implemented by Resolution#modules_for_helpers.
|
92
|
+
|
93
|
+
# :method: # all_helpers_from_path
|
94
|
+
# :call-seq: all_helpers_from_path(path)
|
95
|
+
#
|
96
|
+
# Returns a list of helper names in a given path.
|
48
97
|
#
|
49
|
-
#
|
50
|
-
#
|
98
|
+
# ActionController::Base.all_helpers_from_path 'app/helpers'
|
99
|
+
# # => ["application", "chart", "rubygems"]
|
100
|
+
#
|
101
|
+
#--
|
102
|
+
# Implemented by Resolution#all_helpers_from_path.
|
103
|
+
|
104
|
+
# Declare a controller method as a helper. For example, the following
|
105
|
+
# makes the `current_user` and `logged_in?` controller methods available
|
106
|
+
# to the view:
|
107
|
+
# class ApplicationController < ActionController::Base
|
108
|
+
# helper_method :current_user, :logged_in?
|
109
|
+
#
|
110
|
+
# private
|
111
|
+
# def current_user
|
112
|
+
# @current_user ||= User.find_by(id: session[:user])
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# def logged_in?
|
116
|
+
# current_user != nil
|
117
|
+
# end
|
51
118
|
# end
|
52
|
-
# end
|
53
119
|
#
|
54
120
|
# In a view:
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# *
|
59
|
-
#
|
60
|
-
def helper_method(*
|
61
|
-
|
62
|
-
self._helper_methods +=
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
121
|
+
# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
|
122
|
+
#
|
123
|
+
# #### Parameters
|
124
|
+
# * `method[, method]` - A name or names of a method on the controller to be
|
125
|
+
# made available on the view.
|
126
|
+
def helper_method(*methods)
|
127
|
+
methods.flatten!
|
128
|
+
self._helper_methods += methods
|
129
|
+
|
130
|
+
location = caller_locations(1, 1).first
|
131
|
+
file, line = location.path, location.lineno
|
132
|
+
|
133
|
+
methods.each do |method|
|
134
|
+
# def current_user(...)
|
135
|
+
# controller.send(:'current_user', ...)
|
136
|
+
# end
|
137
|
+
_helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
|
138
|
+
def #{method}(...)
|
139
|
+
controller.send(:'#{method}', ...)
|
140
|
+
end
|
69
141
|
ruby_eval
|
70
142
|
end
|
71
143
|
end
|
72
144
|
|
73
|
-
#
|
145
|
+
# Includes the given modules in the template class.
|
146
|
+
#
|
147
|
+
# Modules can be specified in different ways. All of the following calls include
|
148
|
+
# `FooHelper`:
|
149
|
+
#
|
150
|
+
# # Module, recommended.
|
151
|
+
# helper FooHelper
|
152
|
+
#
|
153
|
+
# # String/symbol without the "helper" suffix, camel or snake case.
|
154
|
+
# helper "Foo"
|
155
|
+
# helper :Foo
|
156
|
+
# helper "foo"
|
157
|
+
# helper :foo
|
74
158
|
#
|
75
|
-
#
|
76
|
-
# * <tt>*args</tt> - Module, Symbol, String
|
77
|
-
# * <tt>block</tt> - A block defining helper methods
|
159
|
+
# The last two assume that `"foo".camelize` returns "Foo".
|
78
160
|
#
|
79
|
-
# When
|
80
|
-
#
|
161
|
+
# When strings or symbols are passed, the method finds the actual module object
|
162
|
+
# using String#constantize. Therefore, if the module has not been yet loaded, it
|
163
|
+
# has to be autoloadable, which is normally the case.
|
81
164
|
#
|
82
|
-
#
|
83
|
-
# and include the module in the template class. The second form illustrates how to include custom helpers
|
84
|
-
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
|
85
|
-
# in one of Rails' standard load paths:
|
86
|
-
# helper :foo # => requires 'foo_helper' and includes FooHelper
|
87
|
-
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
|
165
|
+
# Namespaces are supported. The following calls include `Foo::BarHelper`:
|
88
166
|
#
|
89
|
-
#
|
90
|
-
#
|
167
|
+
# # Module, recommended.
|
168
|
+
# helper Foo::BarHelper
|
91
169
|
#
|
92
|
-
#
|
93
|
-
#
|
170
|
+
# # String/symbol without the "helper" suffix, camel or snake case.
|
171
|
+
# helper "Foo::Bar"
|
172
|
+
# helper :"Foo::Bar"
|
173
|
+
# helper "foo/bar"
|
174
|
+
# helper :"foo/bar"
|
94
175
|
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
176
|
+
# The last two assume that `"foo/bar".camelize` returns "Foo::Bar".
|
177
|
+
#
|
178
|
+
# The method accepts a block too. If present, the block is evaluated in the
|
179
|
+
# context of the controller helper module. This simple call makes the `wadus`
|
180
|
+
# method available in templates of the enclosing controller:
|
181
|
+
#
|
182
|
+
# helper do
|
183
|
+
# def wadus
|
184
|
+
# "wadus"
|
185
|
+
# end
|
99
186
|
# end
|
100
|
-
# end
|
101
187
|
#
|
102
|
-
#
|
103
|
-
# +symbols+, +strings+, +modules+ and blocks.
|
188
|
+
# Furthermore, all the above styles can be mixed together:
|
104
189
|
#
|
105
|
-
#
|
190
|
+
# helper FooHelper, "woo", "bar/baz" do
|
191
|
+
# def wadus
|
192
|
+
# "wadus"
|
193
|
+
# end
|
194
|
+
# end
|
106
195
|
#
|
107
196
|
def helper(*args, &block)
|
108
197
|
modules_for_helpers(args).each do |mod|
|
109
|
-
|
198
|
+
next if _helpers.include?(mod)
|
199
|
+
_helpers_for_modification.include(mod)
|
110
200
|
end
|
111
201
|
|
112
|
-
|
202
|
+
_helpers_for_modification.module_eval(&block) if block_given?
|
113
203
|
end
|
114
204
|
|
115
|
-
# Clears up all existing helpers in this class, only keeping the helper
|
116
|
-
#
|
205
|
+
# Clears up all existing helpers in this class, only keeping the helper with the
|
206
|
+
# same name as this class.
|
117
207
|
def clear_helpers
|
118
208
|
inherited_helper_methods = _helper_methods
|
119
209
|
self._helpers = Module.new
|
@@ -123,72 +213,31 @@ module AbstractController
|
|
123
213
|
default_helper_module! unless anonymous?
|
124
214
|
end
|
125
215
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
# String or Symbol:: :FooBar or "FooBar" becomes "foo_bar_helper",
|
130
|
-
# and "foo_bar_helper.rb" is loaded using require_dependency.
|
131
|
-
#
|
132
|
-
# Module:: No further processing
|
133
|
-
#
|
134
|
-
# After loading the appropriate files, the corresponding modules
|
135
|
-
# are returned.
|
136
|
-
#
|
137
|
-
# ==== Parameters
|
138
|
-
# * <tt>args</tt> - An array of helpers
|
139
|
-
#
|
140
|
-
# ==== Returns
|
141
|
-
# * <tt>Array</tt> - A normalized list of modules for the list of
|
142
|
-
# helpers provided.
|
143
|
-
def modules_for_helpers(args)
|
144
|
-
args.flatten.map! do |arg|
|
145
|
-
case arg
|
146
|
-
when String, Symbol
|
147
|
-
file_name = "#{arg.to_s.underscore}_helper"
|
148
|
-
begin
|
149
|
-
require_dependency(file_name)
|
150
|
-
rescue LoadError => e
|
151
|
-
raise AbstractController::Helpers::MissingHelperError.new(e, file_name)
|
152
|
-
end
|
153
|
-
|
154
|
-
mod_name = file_name.camelize
|
155
|
-
begin
|
156
|
-
mod_name.constantize
|
157
|
-
rescue LoadError
|
158
|
-
# dependencies.rb gives a similar error message but its wording is
|
159
|
-
# not as clear because it mentions autoloading. To the user all it
|
160
|
-
# matters is that a helper module couldn't be loaded, autoloading
|
161
|
-
# is an internal mechanism that should not leak.
|
162
|
-
raise NameError, "Couldn't find #{mod_name}, expected it to be defined in helpers/#{file_name}.rb"
|
163
|
-
end
|
164
|
-
when Module
|
165
|
-
arg
|
166
|
-
else
|
167
|
-
raise ArgumentError, "helper must be a String, Symbol, or Module"
|
168
|
-
end
|
216
|
+
def _helpers_for_modification
|
217
|
+
unless @_helpers
|
218
|
+
self._helpers = define_helpers_module(self, superclass._helpers)
|
169
219
|
end
|
220
|
+
_helpers
|
170
221
|
end
|
171
222
|
|
172
223
|
private
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
224
|
+
def define_helpers_module(klass, helpers = nil)
|
225
|
+
# In some tests inherited is called explicitly. In that case, just return the
|
226
|
+
# module from the first time it was defined
|
227
|
+
return klass.const_get(:HelperMethods) if klass.const_defined?(:HelperMethods, false)
|
228
|
+
|
229
|
+
mod = Module.new
|
230
|
+
klass.const_set(:HelperMethods, mod)
|
231
|
+
mod.include(helpers) if helpers
|
232
|
+
mod
|
233
|
+
end
|
182
234
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
rescue NameError => e
|
190
|
-
raise e unless e.missing_name? "#{module_name}Helper"
|
191
|
-
end
|
235
|
+
def default_helper_module!
|
236
|
+
helper_prefix = name.delete_suffix("Controller")
|
237
|
+
helper(helper_prefix)
|
238
|
+
rescue NameError => e
|
239
|
+
raise unless e.missing_name?("#{helper_prefix}Helper")
|
240
|
+
end
|
192
241
|
end
|
193
242
|
end
|
194
243
|
end
|
@@ -1,3 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/core_ext/module/introspection"
|
6
|
+
|
1
7
|
module AbstractController
|
2
8
|
module Railties
|
3
9
|
module RoutesHelpers
|
@@ -5,10 +11,11 @@ module AbstractController
|
|
5
11
|
Module.new do
|
6
12
|
define_method(:inherited) do |klass|
|
7
13
|
super(klass)
|
8
|
-
|
9
|
-
|
14
|
+
|
15
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
16
|
+
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
|
10
17
|
else
|
11
|
-
klass.
|
18
|
+
klass.include(routes.url_helpers(include_path_helpers))
|
12
19
|
end
|
13
20
|
end
|
14
21
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "abstract_controller/error"
|
6
|
+
require "action_view"
|
7
|
+
require "action_view/view_paths"
|
8
|
+
require "set"
|
6
9
|
|
7
10
|
module AbstractController
|
8
11
|
class DoubleRenderError < Error
|
9
|
-
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...)
|
12
|
+
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...); return\"."
|
10
13
|
|
11
14
|
def initialize(message = nil)
|
12
15
|
super(message || DEFAULT_MESSAGE)
|
@@ -17,66 +20,58 @@ module AbstractController
|
|
17
20
|
extend ActiveSupport::Concern
|
18
21
|
include ActionView::ViewPaths
|
19
22
|
|
20
|
-
#
|
21
|
-
# sticks the result in self.response_body
|
22
|
-
#
|
23
|
+
# Normalizes arguments and options, and then delegates to render_to_body and
|
24
|
+
# sticks the result in `self.response_body`.
|
25
|
+
#
|
26
|
+
# Supported options depend on the underlying `render_to_body` implementation.
|
23
27
|
def render(*args, &block)
|
24
28
|
options = _normalize_render(*args, &block)
|
25
|
-
|
26
|
-
|
27
|
-
|
29
|
+
rendered_body = render_to_body(options)
|
30
|
+
if options[:html]
|
31
|
+
_set_html_content_type
|
32
|
+
else
|
33
|
+
_set_rendered_content_type rendered_format
|
34
|
+
end
|
35
|
+
_set_vary_header
|
36
|
+
self.response_body = rendered_body
|
28
37
|
end
|
29
38
|
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# It is similar to render, except that it does not
|
33
|
-
# set the response_body and it should be guaranteed
|
34
|
-
# to always return a string.
|
39
|
+
# Similar to #render, but only returns the rendered template as a string,
|
40
|
+
# instead of setting `self.response_body`.
|
35
41
|
#
|
36
|
-
# If a component extends the semantics of response_body
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# overridden in order to still return a string.
|
40
|
-
# :api: plugin
|
42
|
+
# If a component extends the semantics of `response_body` (as ActionController
|
43
|
+
# extends it to be anything that responds to the method each), this method needs
|
44
|
+
# to be overridden in order to still return a string.
|
41
45
|
def render_to_string(*args, &block)
|
42
46
|
options = _normalize_render(*args, &block)
|
43
47
|
render_to_body(options)
|
44
48
|
end
|
45
49
|
|
46
50
|
# Performs the actual template rendering.
|
47
|
-
# :api: public
|
48
51
|
def render_to_body(options = {})
|
49
52
|
end
|
50
53
|
|
51
|
-
# Returns Content-Type of rendered content
|
52
|
-
# :api: public
|
54
|
+
# Returns `Content-Type` of rendered content.
|
53
55
|
def rendered_format
|
54
|
-
Mime
|
56
|
+
Mime[:text]
|
55
57
|
end
|
56
58
|
|
57
|
-
DEFAULT_PROTECTED_INSTANCE_VARIABLES =
|
58
|
-
@_action_name @_response_body @_formats @_prefixes @_config
|
59
|
-
@_view_context_class @_view_renderer @_lookup_context
|
60
|
-
@_routes @_db_runtime
|
61
|
-
).map(&:to_sym)
|
59
|
+
DEFAULT_PROTECTED_INSTANCE_VARIABLES = %i(@_action_name @_response_body @_formats @_prefixes)
|
62
60
|
|
63
|
-
# This method should return a hash with assigns.
|
64
|
-
#
|
65
|
-
# :api: public
|
61
|
+
# This method should return a hash with assigns. You can overwrite this
|
62
|
+
# configuration per controller.
|
66
63
|
def view_assigns
|
67
|
-
|
68
|
-
variables = instance_variables
|
64
|
+
variables = instance_variables - _protected_ivars
|
69
65
|
|
70
|
-
variables.
|
71
|
-
variables.each_with_object({}) { |name, hash|
|
66
|
+
variables.each_with_object({}) do |name, hash|
|
72
67
|
hash[name.slice(1, name.length)] = instance_variable_get(name)
|
73
|
-
|
68
|
+
end
|
74
69
|
end
|
75
70
|
|
76
|
-
|
77
|
-
# render "foo
|
78
|
-
# :
|
79
|
-
def _normalize_args(action=nil, options={})
|
71
|
+
private
|
72
|
+
# Normalize args by converting `render "foo"` to `render action: "foo"` and
|
73
|
+
# `render "foo/bar"` to `render file: "foo/bar"`.
|
74
|
+
def _normalize_args(action = nil, options = {}) # :doc:
|
80
75
|
if action.respond_to?(:permitted?)
|
81
76
|
if action.permitted?
|
82
77
|
action
|
@@ -91,35 +86,40 @@ module AbstractController
|
|
91
86
|
end
|
92
87
|
|
93
88
|
# Normalize options.
|
94
|
-
# :
|
95
|
-
def _normalize_options(options)
|
89
|
+
def _normalize_options(options) # :doc:
|
96
90
|
options
|
97
91
|
end
|
98
92
|
|
99
93
|
# Process extra options.
|
100
|
-
# :
|
101
|
-
def _process_options(options)
|
94
|
+
def _process_options(options) # :doc:
|
102
95
|
options
|
103
96
|
end
|
104
97
|
|
105
98
|
# Process the rendered format.
|
106
|
-
# :
|
107
|
-
|
99
|
+
def _process_format(format) # :nodoc:
|
100
|
+
end
|
101
|
+
|
102
|
+
def _process_variant(options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def _set_html_content_type # :nodoc:
|
106
|
+
end
|
107
|
+
|
108
|
+
def _set_vary_header # :nodoc:
|
109
|
+
end
|
110
|
+
|
111
|
+
def _set_rendered_content_type(format) # :nodoc:
|
108
112
|
end
|
109
113
|
|
110
114
|
# Normalize args and options.
|
111
|
-
# :
|
112
|
-
def _normalize_render(*args, &block)
|
115
|
+
def _normalize_render(*args, &block) # :nodoc:
|
113
116
|
options = _normalize_args(*args, &block)
|
114
|
-
|
115
|
-
if defined?(request) && request && request.variant.present?
|
116
|
-
options[:variant] = request.variant
|
117
|
-
end
|
117
|
+
_process_variant(options)
|
118
118
|
_normalize_options(options)
|
119
119
|
options
|
120
120
|
end
|
121
121
|
|
122
|
-
def _protected_ivars
|
122
|
+
def _protected_ivars
|
123
123
|
DEFAULT_PROTECTED_INSTANCE_VARIABLES
|
124
124
|
end
|
125
125
|
end
|
@@ -1,27 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/html_safe_translation"
|
6
|
+
|
1
7
|
module AbstractController
|
2
8
|
module Translation
|
3
|
-
# Delegates to
|
9
|
+
# Delegates to `I18n.translate`.
|
4
10
|
#
|
5
11
|
# When the given key starts with a period, it will be scoped by the current
|
6
|
-
# controller and action. So if you call
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
def translate(
|
12
|
-
key
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# controller and action. So if you call `translate(".foo")` from
|
13
|
+
# `PeopleController#index`, it will convert the call to
|
14
|
+
# `I18n.translate("people.index.foo")`. This makes it less repetitive to
|
15
|
+
# translate many keys within the same controller / action and gives you a simple
|
16
|
+
# framework for scoping them consistently.
|
17
|
+
def translate(key, **options)
|
18
|
+
if key&.start_with?(".")
|
19
|
+
path = controller_path.tr("/", ".")
|
20
|
+
defaults = [:"#{path}#{key}"]
|
21
|
+
defaults << options[:default] if options[:default]
|
22
|
+
options[:default] = defaults.flatten
|
23
|
+
key = "#{path}.#{action_name}#{key}"
|
24
|
+
end
|
25
|
+
|
26
|
+
if options[:default] && ActiveSupport::HtmlSafeTranslation.html_safe_translation_key?(key)
|
27
|
+
options[:default] = Array(options[:default]).map do |value|
|
28
|
+
value.is_a?(String) ? ERB::Util.html_escape(value) : value
|
29
|
+
end
|
16
30
|
end
|
17
31
|
|
18
|
-
|
32
|
+
ActiveSupport::HtmlSafeTranslation.translate(key, **options)
|
19
33
|
end
|
20
34
|
alias :t :translate
|
21
35
|
|
22
|
-
# Delegates to
|
23
|
-
def localize(
|
24
|
-
I18n.localize(
|
36
|
+
# Delegates to `I18n.localize`.
|
37
|
+
def localize(object, **options)
|
38
|
+
I18n.localize(object, **options)
|
25
39
|
end
|
26
40
|
alias :l :localize
|
27
41
|
end
|