actionpack 4.2.11.1 → 6.1.3.2

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

Potentially problematic release.


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

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +291 -489
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -9
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +81 -51
  7. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +64 -17
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +61 -33
  10. data/lib/abstract_controller/collector.rb +9 -13
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +115 -99
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +21 -3
  15. data/lib/abstract_controller/rendering.rb +48 -47
  16. data/lib/abstract_controller/translation.rb +17 -8
  17. data/lib/abstract_controller/url_for.rb +2 -0
  18. data/lib/abstract_controller.rb +13 -5
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +150 -0
  21. data/lib/action_controller/base.rb +29 -24
  22. data/lib/action_controller/caching.rb +12 -57
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +17 -19
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +134 -46
  27. data/lib/action_controller/metal/content_security_policy.rb +51 -0
  28. data/lib/action_controller/metal/cookies.rb +6 -4
  29. data/lib/action_controller/metal/data_streaming.rb +30 -50
  30. data/lib/action_controller/metal/default_headers.rb +17 -0
  31. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  32. data/lib/action_controller/metal/etag_with_template_digest.rb +21 -16
  33. data/lib/action_controller/metal/exceptions.rb +63 -15
  34. data/lib/action_controller/metal/flash.rb +9 -8
  35. data/lib/action_controller/metal/head.rb +26 -21
  36. data/lib/action_controller/metal/helpers.rb +37 -18
  37. data/lib/action_controller/metal/http_authentication.rb +81 -73
  38. data/lib/action_controller/metal/implicit_render.rb +53 -9
  39. data/lib/action_controller/metal/instrumentation.rb +32 -35
  40. data/lib/action_controller/metal/live.rb +102 -120
  41. data/lib/action_controller/metal/logging.rb +20 -0
  42. data/lib/action_controller/metal/mime_responds.rb +49 -47
  43. data/lib/action_controller/metal/parameter_encoding.rb +82 -0
  44. data/lib/action_controller/metal/params_wrapper.rb +83 -66
  45. data/lib/action_controller/metal/permissions_policy.rb +46 -0
  46. data/lib/action_controller/metal/redirecting.rb +53 -32
  47. data/lib/action_controller/metal/renderers.rb +87 -44
  48. data/lib/action_controller/metal/rendering.rb +77 -50
  49. data/lib/action_controller/metal/request_forgery_protection.rb +267 -103
  50. data/lib/action_controller/metal/rescue.rb +10 -17
  51. data/lib/action_controller/metal/streaming.rb +12 -11
  52. data/lib/action_controller/metal/strong_parameters.rb +714 -186
  53. data/lib/action_controller/metal/testing.rb +2 -17
  54. data/lib/action_controller/metal/url_for.rb +19 -10
  55. data/lib/action_controller/metal.rb +104 -87
  56. data/lib/action_controller/railtie.rb +28 -10
  57. data/lib/action_controller/railties/helpers.rb +3 -1
  58. data/lib/action_controller/renderer.rb +141 -0
  59. data/lib/action_controller/template_assertions.rb +11 -0
  60. data/lib/action_controller/test_case.rb +296 -422
  61. data/lib/action_controller.rb +34 -23
  62. data/lib/action_dispatch/http/cache.rb +107 -56
  63. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  64. data/lib/action_dispatch/http/content_security_policy.rb +286 -0
  65. data/lib/action_dispatch/http/filter_parameters.rb +32 -25
  66. data/lib/action_dispatch/http/filter_redirect.rb +10 -12
  67. data/lib/action_dispatch/http/headers.rb +55 -22
  68. data/lib/action_dispatch/http/mime_negotiation.rb +79 -51
  69. data/lib/action_dispatch/http/mime_type.rb +153 -121
  70. data/lib/action_dispatch/http/mime_types.rb +20 -6
  71. data/lib/action_dispatch/http/parameters.rb +90 -40
  72. data/lib/action_dispatch/http/permissions_policy.rb +173 -0
  73. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  74. data/lib/action_dispatch/http/request.rb +226 -121
  75. data/lib/action_dispatch/http/response.rb +248 -113
  76. data/lib/action_dispatch/http/upload.rb +21 -7
  77. data/lib/action_dispatch/http/url.rb +182 -100
  78. data/lib/action_dispatch/journey/formatter.rb +90 -43
  79. data/lib/action_dispatch/journey/gtg/builder.rb +28 -41
  80. data/lib/action_dispatch/journey/gtg/simulator.rb +11 -16
  81. data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -21
  82. data/lib/action_dispatch/journey/nfa/dot.rb +3 -14
  83. data/lib/action_dispatch/journey/nodes/node.rb +29 -15
  84. data/lib/action_dispatch/journey/parser.rb +17 -16
  85. data/lib/action_dispatch/journey/parser.y +4 -3
  86. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  87. data/lib/action_dispatch/journey/path/pattern.rb +58 -54
  88. data/lib/action_dispatch/journey/route.rb +100 -32
  89. data/lib/action_dispatch/journey/router/utils.rb +29 -18
  90. data/lib/action_dispatch/journey/router.rb +55 -51
  91. data/lib/action_dispatch/journey/routes.rb +17 -17
  92. data/lib/action_dispatch/journey/scanner.rb +26 -17
  93. data/lib/action_dispatch/journey/visitors.rb +98 -54
  94. data/lib/action_dispatch/journey.rb +5 -5
  95. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  96. data/lib/action_dispatch/middleware/callbacks.rb +3 -6
  97. data/lib/action_dispatch/middleware/cookies.rb +347 -217
  98. data/lib/action_dispatch/middleware/debug_exceptions.rb +135 -63
  99. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  100. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  101. data/lib/action_dispatch/middleware/exception_wrapper.rb +115 -71
  102. data/lib/action_dispatch/middleware/executor.rb +21 -0
  103. data/lib/action_dispatch/middleware/flash.rb +78 -54
  104. data/lib/action_dispatch/middleware/host_authorization.rb +130 -0
  105. data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
  106. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  107. data/lib/action_dispatch/middleware/remote_ip.rb +53 -45
  108. data/lib/action_dispatch/middleware/request_id.rb +17 -10
  109. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
  110. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  111. data/lib/action_dispatch/middleware/session/cookie_store.rb +74 -75
  112. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  113. data/lib/action_dispatch/middleware/show_exceptions.rb +28 -23
  114. data/lib/action_dispatch/middleware/ssl.rb +118 -35
  115. data/lib/action_dispatch/middleware/stack.rb +82 -41
  116. data/lib/action_dispatch/middleware/static.rb +156 -89
  117. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -14
  121. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  125. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  129. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +105 -8
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  135. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  137. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  138. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  139. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  140. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +87 -64
  141. data/lib/action_dispatch/railtie.rb +27 -13
  142. data/lib/action_dispatch/request/session.rb +109 -61
  143. data/lib/action_dispatch/request/utils.rb +90 -23
  144. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  145. data/lib/action_dispatch/routing/inspector.rb +141 -102
  146. data/lib/action_dispatch/routing/mapper.rb +811 -473
  147. data/lib/action_dispatch/routing/polymorphic_routes.rb +167 -143
  148. data/lib/action_dispatch/routing/redirection.rb +37 -27
  149. data/lib/action_dispatch/routing/route_set.rb +363 -331
  150. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  151. data/lib/action_dispatch/routing/url_for.rb +66 -26
  152. data/lib/action_dispatch/routing.rb +36 -36
  153. data/lib/action_dispatch/system_test_case.rb +190 -0
  154. data/lib/action_dispatch/system_testing/browser.rb +86 -0
  155. data/lib/action_dispatch/system_testing/driver.rb +67 -0
  156. data/lib/action_dispatch/system_testing/server.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +138 -0
  158. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +29 -0
  159. data/lib/action_dispatch/testing/assertion_response.rb +46 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +44 -22
  161. data/lib/action_dispatch/testing/assertions/routing.rb +47 -31
  162. data/lib/action_dispatch/testing/assertions.rb +6 -4
  163. data/lib/action_dispatch/testing/integration.rb +391 -220
  164. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  165. data/lib/action_dispatch/testing/test_process.rb +53 -22
  166. data/lib/action_dispatch/testing/test_request.rb +27 -34
  167. data/lib/action_dispatch/testing/test_response.rb +11 -11
  168. data/lib/action_dispatch.rb +35 -21
  169. data/lib/action_pack/gem_version.rb +6 -4
  170. data/lib/action_pack/version.rb +3 -1
  171. data/lib/action_pack.rb +4 -2
  172. metadata +78 -48
  173. data/lib/action_controller/metal/force_ssl.rb +0 -97
  174. data/lib/action_controller/metal/hide_actions.rb +0 -40
  175. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  176. data/lib/action_controller/middleware.rb +0 -39
  177. data/lib/action_controller/model_naming.rb +0 -12
  178. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  179. data/lib/action_dispatch/journey/backwards.rb +0 -5
  180. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  181. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  182. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  183. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  184. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  185. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  186. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  187. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,16 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController
2
4
  class ActionControllerError < StandardError #:nodoc:
3
5
  end
4
6
 
5
7
  class BadRequest < ActionControllerError #:nodoc:
6
- attr_reader :original_exception
7
-
8
- def initialize(type = nil, e = nil)
9
- return super() unless type && e
10
-
11
- super("Invalid #{type} parameters: #{e.message}")
12
- @original_exception = e
13
- set_backtrace e.backtrace
8
+ def initialize(msg = nil)
9
+ super(msg)
10
+ set_backtrace $!.backtrace if $!
14
11
  end
15
12
  end
16
13
 
@@ -19,32 +16,62 @@ module ActionController
19
16
 
20
17
  class RoutingError < ActionControllerError #:nodoc:
21
18
  attr_reader :failures
22
- def initialize(message, failures=[])
19
+ def initialize(message, failures = [])
23
20
  super(message)
24
21
  @failures = failures
25
22
  end
26
23
  end
27
24
 
28
- class ActionController::UrlGenerationError < ActionControllerError #:nodoc:
25
+ class UrlGenerationError < ActionControllerError #:nodoc:
26
+ attr_reader :routes, :route_name, :method_name
27
+
28
+ def initialize(message, routes = nil, route_name = nil, method_name = nil)
29
+ @routes = routes
30
+ @route_name = route_name
31
+ @method_name = method_name
32
+
33
+ super(message)
34
+ end
35
+
36
+ class Correction
37
+ def initialize(error)
38
+ @error = error
39
+ end
40
+
41
+ def corrections
42
+ if @error.method_name
43
+ maybe_these = @error.routes.named_routes.helper_names.grep(/#{@error.route_name}/)
44
+ maybe_these -= [@error.method_name.to_s] # remove exact match
45
+
46
+ maybe_these.sort_by { |n|
47
+ DidYouMean::Jaro.distance(@error.route_name, n)
48
+ }.reverse.first(4)
49
+ else
50
+ []
51
+ end
52
+ end
53
+ end
54
+
55
+ # We may not have DYM, and DYM might not let us register error handlers
56
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
57
+ DidYouMean.correct_error(self, Correction)
58
+ end
29
59
  end
30
60
 
31
61
  class MethodNotAllowed < ActionControllerError #:nodoc:
32
62
  def initialize(*allowed_methods)
33
- super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
63
+ super("Only #{allowed_methods.to_sentence} requests are allowed.")
34
64
  end
35
65
  end
36
66
 
37
67
  class NotImplemented < MethodNotAllowed #:nodoc:
38
68
  end
39
69
 
40
- class UnknownController < ActionControllerError #:nodoc:
41
- end
42
-
43
70
  class MissingFile < ActionControllerError #:nodoc:
44
71
  end
45
72
 
46
73
  class SessionOverflowError < ActionControllerError #:nodoc:
47
- DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
74
+ DEFAULT_MESSAGE = "Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data."
48
75
 
49
76
  def initialize(message = nil)
50
77
  super(message || DEFAULT_MESSAGE)
@@ -56,4 +83,25 @@ module ActionController
56
83
 
57
84
  class UnknownFormat < ActionControllerError #:nodoc:
58
85
  end
86
+
87
+ # Raised when a nested respond_to is triggered and the content types of each
88
+ # are incompatible. For example:
89
+ #
90
+ # respond_to do |outer_type|
91
+ # outer_type.js do
92
+ # respond_to do |inner_type|
93
+ # inner_type.html { render body: "HTML" }
94
+ # end
95
+ # end
96
+ # end
97
+ class RespondToMismatchError < ActionControllerError
98
+ DEFAULT_MESSAGE = "respond_to was called multiple times and matched with conflicting formats in this action. Please note that you may only call respond_to and match on a single format per action."
99
+
100
+ def initialize(message = nil)
101
+ super(message || DEFAULT_MESSAGE)
102
+ end
103
+ end
104
+
105
+ class MissingExactTemplate < UnknownFormat #:nodoc:
106
+ end
59
107
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController #:nodoc:
2
4
  module Flash
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :_flash_types, instance_accessor: false
7
- self._flash_types = []
8
+ class_attribute :_flash_types, instance_accessor: false, default: []
8
9
 
9
10
  delegate :flash, to: :request
10
11
  add_flash_types(:alert, :notice)
@@ -35,26 +36,26 @@ module ActionController #:nodoc:
35
36
  define_method(type) do
36
37
  request.flash[type]
37
38
  end
38
- helper_method type
39
+ helper_method(type) if respond_to?(:helper_method)
39
40
 
40
41
  self._flash_types += [type]
41
42
  end
42
43
  end
43
44
  end
44
45
 
45
- protected
46
- def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
46
+ private
47
+ def redirect_to(options = {}, response_options_and_flash = {}) #:doc:
47
48
  self.class._flash_types.each do |flash_type|
48
- if type = response_status_and_flash.delete(flash_type)
49
+ if type = response_options_and_flash.delete(flash_type)
49
50
  flash[flash_type] = type
50
51
  end
51
52
  end
52
53
 
53
- if other_flashes = response_status_and_flash.delete(:flash)
54
+ if other_flashes = response_options_and_flash.delete(:flash)
54
55
  flash.update(other_flashes)
55
56
  end
56
57
 
57
- super(options, response_status_and_flash)
58
+ super(options, response_options_and_flash)
58
59
  end
59
60
  end
60
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController
2
4
  module Head
3
5
  # Returns a response that has no content (merely headers). The options
@@ -17,42 +19,45 @@ module ActionController
17
19
  #
18
20
  # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list of valid +status+ symbols.
19
21
  def head(status, options = {})
20
- options, status = status, nil if status.is_a?(Hash)
21
- status ||= options.delete(:status) || :ok
22
+ if status.is_a?(Hash)
23
+ raise ArgumentError, "#{status.inspect} is not a valid value for `status`."
24
+ end
25
+
26
+ status ||= :ok
27
+
22
28
  location = options.delete(:location)
23
29
  content_type = options.delete(:content_type)
24
30
 
25
31
  options.each do |key, value|
26
- headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s
32
+ headers[key.to_s.split(/[-_]/).each { |v| v[0] = v[0].upcase }.join("-")] = value.to_s
27
33
  end
28
34
 
29
35
  self.status = status
30
36
  self.location = url_for(location) if location
31
37
 
32
- self.response_body = ""
38
+ if include_content?(response_code)
39
+ unless self.media_type
40
+ self.content_type = content_type || (Mime[formats.first] if formats) || Mime[:html]
41
+ end
33
42
 
34
- if include_content?(self.response_code)
35
- self.content_type = content_type || (Mime[formats.first] if formats)
36
- self.response.charset = false if self.response
37
- else
38
- headers.delete('Content-Type')
39
- headers.delete('Content-Length')
43
+ response.charset = false
40
44
  end
41
-
45
+
46
+ self.response_body = ""
47
+
42
48
  true
43
49
  end
44
50
 
45
51
  private
46
- # :nodoc:
47
- def include_content?(status)
48
- case status
49
- when 100..199
50
- false
51
- when 204, 205, 304
52
- false
53
- else
54
- true
52
+ def include_content?(status)
53
+ case status
54
+ when 100..199
55
+ false
56
+ when 204, 205, 304
57
+ false
58
+ else
59
+ true
60
+ end
55
61
  end
56
- end
57
62
  end
58
63
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController
2
4
  # The \Rails framework provides a large number of helpers for working with assets, dates, forms,
3
5
  # numbers and model objects, to name a few. These helpers are available to all templates
@@ -5,11 +7,16 @@ module ActionController
5
7
  #
6
8
  # In addition to using the standard template helpers provided, creating custom helpers to
7
9
  # extract complicated logic or reusable functionality is strongly encouraged. By default, each controller
8
- # will include all helpers. These helpers are only accessible on the controller through <tt>.helpers</tt>
10
+ # will include all helpers. These helpers are only accessible on the controller through <tt>#helpers</tt>
11
+ #
12
+ # In previous versions of \Rails the controller will include a helper which
13
+ # matches the name of the controller, e.g., <tt>MyController</tt> will automatically
14
+ # include <tt>MyHelper</tt>. You can revert to the old behavior with the following:
9
15
  #
10
- # In previous versions of \Rails the controller will include a helper whose
11
- # name matches that of the controller, e.g., <tt>MyController</tt> will automatically
12
- # include <tt>MyHelper</tt>. To return old behavior set +config.action_controller.include_all_helpers+ to +false+.
16
+ # # config/application.rb
17
+ # class Application < Rails::Application
18
+ # config.action_controller.include_all_helpers = false
19
+ # end
13
20
  #
14
21
  # Additional helpers can be specified using the +helper+ class method in ActionController::Base or any
15
22
  # controller which inherits from it.
@@ -32,7 +39,7 @@ module ActionController
32
39
  # end
33
40
  # end
34
41
  #
35
- # Then, in any view rendered by <tt>EventController</tt>, the <tt>format_time</tt> method can be called:
42
+ # Then, in any view rendered by <tt>EventsController</tt>, the <tt>format_time</tt> method can be called:
36
43
  #
37
44
  # <% @events.each do |event| -%>
38
45
  # <p>
@@ -44,7 +51,7 @@ module ActionController
44
51
  # the output might look like this:
45
52
  #
46
53
  # 23 Aug 11:30 | Carolina Railhawks Soccer Match
47
- # N/A | Carolina Railhaws Training Workshop
54
+ # N/A | Carolina Railhawks Training Workshop
48
55
  #
49
56
  module Helpers
50
57
  extend ActiveSupport::Concern
@@ -53,9 +60,8 @@ module ActionController
53
60
  include AbstractController::Helpers
54
61
 
55
62
  included do
56
- class_attribute :helpers_path, :include_all_helpers
57
- self.helpers_path ||= []
58
- self.include_all_helpers = true
63
+ class_attribute :helpers_path, default: []
64
+ class_attribute :include_all_helpers, default: true
59
65
  end
60
66
 
61
67
  module ClassMethods
@@ -71,10 +77,15 @@ module ActionController
71
77
  attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
72
78
  end
73
79
 
74
- # Provides a proxy to access helpers methods from outside the view.
80
+ # Provides a proxy to access helper methods from outside the view.
81
+ #
82
+ # Note that the proxy is rendered under a different view context.
83
+ # This may cause incorrect behaviour with capture methods. Consider
84
+ # using {helper}[rdoc-ref:AbstractController::Helpers::ClassMethods#helper]
85
+ # instead when using +capture+.
75
86
  def helpers
76
- @helper_proxy ||= begin
77
- proxy = ActionView::Base.new
87
+ @helper_proxy ||= begin
88
+ proxy = ActionView::Base.empty
78
89
  proxy.config = config.inheritable_copy
79
90
  proxy.extend(_helpers)
80
91
  end
@@ -93,10 +104,13 @@ module ActionController
93
104
  super(args)
94
105
  end
95
106
 
107
+ # Returns a list of helper names in a given path.
108
+ #
109
+ # ActionController::Base.all_helpers_from_path 'app/helpers'
110
+ # # => ["application", "chart", "rubygems"]
96
111
  def all_helpers_from_path(path)
97
112
  helpers = Array(path).flat_map do |_path|
98
- extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
99
- names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
113
+ names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
100
114
  names.sort!
101
115
  end
102
116
  helpers.uniq!
@@ -104,10 +118,15 @@ module ActionController
104
118
  end
105
119
 
106
120
  private
107
- # Extract helper names from files in <tt>app/helpers/**/*_helper.rb</tt>
108
- def all_application_helpers
109
- all_helpers_from_path(helpers_path)
110
- end
121
+ # Extract helper names from files in <tt>app/helpers/**/*_helper.rb</tt>
122
+ def all_application_helpers
123
+ all_helpers_from_path(helpers_path)
124
+ end
125
+ end
126
+
127
+ # Provides a proxy to access helper methods from outside the view.
128
+ def helpers
129
+ @_helper_proxy ||= view_context
111
130
  end
112
131
  end
113
132
  end