actionpack 4.2.10 → 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 +5 -5
  2. data/CHANGELOG.md +291 -479
  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 +82 -50
  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 -49
  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,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) # def html(*args, &block)
10
- custom(Mime::#{const}, *args, &block) # custom(Mime::HTML, *args, &block)
11
- end # end
10
+ def #{sym}(*args, &block)
11
+ custom(Mime[:#{sym}], *args, &block)
12
+ end
12
13
  RUBY
13
14
  end
14
15
 
@@ -17,24 +18,19 @@ module AbstractController
17
18
  end
18
19
 
19
20
  Mime::Type.register_callback do |mime|
20
- generate_method_for_mime(mime) unless self.instance_methods.include?(mime.to_sym)
21
+ generate_method_for_mime(mime) unless instance_methods.include?(mime.to_sym)
21
22
  end
22
23
 
23
- protected
24
-
24
+ private
25
25
  def method_missing(symbol, &block)
26
- const_name = symbol.upcase
27
-
28
- unless Mime.const_defined?(const_name)
26
+ unless mime_constant = Mime[symbol]
29
27
  raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
30
- "http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
28
+ "https://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
31
29
  "If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
32
30
  "be sure to nest your variant response within a format response: " \
33
31
  "format.html { |html| html.tablet { ... } }"
34
32
  end
35
33
 
36
- mime_constant = Mime.const_get(const_name)
37
-
38
34
  if Mime::SET.include?(mime_constant)
39
35
  AbstractController::Collector.generate_method_for_mime(mime_constant)
40
36
  send(symbol, &block)
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractController
4
+ class Error < StandardError #:nodoc:
5
+ end
6
+ end
@@ -1,15 +1,25 @@
1
- require 'active_support/dependencies'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/dependencies"
2
4
 
3
5
  module AbstractController
4
6
  module Helpers
5
7
  extend ActiveSupport::Concern
6
8
 
7
9
  included do
8
- class_attribute :_helpers
9
- self._helpers = Module.new
10
+ class_attribute :_helper_methods, default: Array.new
11
+
12
+ # This is here so that it is always higher in the inheritance chain than
13
+ # the definition in lib/action_view/rendering.rb
14
+ redefine_singleton_method(:_helpers) do
15
+ if @_helpers ||= nil
16
+ @_helpers
17
+ else
18
+ superclass._helpers
19
+ end
20
+ end
10
21
 
11
- class_attribute :_helper_methods
12
- self._helper_methods = Array.new
22
+ self._helpers = define_helpers_module(self)
13
23
  end
14
24
 
15
25
  class MissingHelperError < LoadError
@@ -18,7 +28,7 @@ module AbstractController
18
28
  @path = "helpers/#{path}.rb"
19
29
  set_backtrace error.backtrace
20
30
 
21
- if error.path =~ /^#{path}(\.rb)?$/
31
+ if /^#{path}(\.rb)?$/.match?(error.path)
22
32
  super("Missing helper file helpers/%s.rb" % path)
23
33
  else
24
34
  raise error
@@ -26,19 +36,27 @@ module AbstractController
26
36
  end
27
37
  end
28
38
 
39
+ def _helpers
40
+ self.class._helpers
41
+ end
42
+
29
43
  module ClassMethods
30
44
  # When a class is inherited, wrap its helper module in a new module.
31
45
  # This ensures that the parent class's module can be changed
32
46
  # independently of the child class's.
33
47
  def inherited(klass)
34
- helpers = _helpers
35
- klass._helpers = Module.new { include helpers }
48
+ # Inherited from parent by default
49
+ klass._helpers = nil
50
+
36
51
  klass.class_eval { default_helper_module! } unless klass.anonymous?
37
52
  super
38
53
  end
39
54
 
55
+ attr_writer :_helpers
56
+
40
57
  # Declare a controller method as a helper. For example, the following
41
- # makes the +current_user+ controller method available to the view:
58
+ # makes the +current_user+ and +logged_in?+ controller methods available
59
+ # to the view:
42
60
  # class ApplicationController < ActionController::Base
43
61
  # helper_method :current_user, :logged_in?
44
62
  #
@@ -57,59 +75,81 @@ module AbstractController
57
75
  # ==== Parameters
58
76
  # * <tt>method[, method]</tt> - A name or names of a method on the controller
59
77
  # to be made available on the view.
60
- def helper_method(*meths)
61
- meths.flatten!
62
- self._helper_methods += meths
63
-
64
- meths.each do |meth|
65
- _helpers.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
66
- def #{meth}(*args, &blk) # def current_user(*args, &blk)
67
- controller.send(%(#{meth}), *args, &blk) # controller.send(:current_user, *args, &blk)
68
- end # end
78
+ def helper_method(*methods)
79
+ methods.flatten!
80
+ self._helper_methods += methods
81
+
82
+ location = caller_locations(1, 1).first
83
+ file, line = location.path, location.lineno
84
+
85
+ methods.each do |method|
86
+ _helpers_for_modification.class_eval <<-ruby_eval, file, line
87
+ def #{method}(*args, &block) # def current_user(*args, &block)
88
+ controller.send(:'#{method}', *args, &block) # controller.send(:'current_user', *args, &block)
89
+ end # end
90
+ ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
69
91
  ruby_eval
70
92
  end
71
93
  end
72
94
 
73
- # The +helper+ class method can take a series of helper module names, a block, or both.
95
+ # Includes the given modules in the template class.
96
+ #
97
+ # Modules can be specified in different ways. All of the following calls
98
+ # include +FooHelper+:
99
+ #
100
+ # # Module, recommended.
101
+ # helper FooHelper
102
+ #
103
+ # # String/symbol without the "helper" suffix, camel or snake case.
104
+ # helper "Foo"
105
+ # helper :Foo
106
+ # helper "foo"
107
+ # helper :foo
74
108
  #
75
- # ==== Options
76
- # * <tt>*args</tt> - Module, Symbol, String
77
- # * <tt>block</tt> - A block defining helper methods
109
+ # The last two assume that <tt>"foo".camelize</tt> returns "Foo".
78
110
  #
79
- # When the argument is a module it will be included directly in the template class.
80
- # helper FooHelper # => includes FooHelper
111
+ # When strings or symbols are passed, the method finds the actual module
112
+ # object using +String#constantize+. Therefore, if the module has not been
113
+ # yet loaded, it has to be autoloadable, which is normally the case.
81
114
  #
82
- # When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
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
115
+ # Namespaces are supported. The following calls include +Foo::BarHelper+:
88
116
  #
89
- # Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available
90
- # to the template.
117
+ # # Module, recommended.
118
+ # helper Foo::BarHelper
91
119
  #
92
- # # One line
93
- # helper { def hello() "Hello, world!" end }
120
+ # # String/symbol without the "helper" suffix, camel or snake case.
121
+ # helper "Foo::Bar"
122
+ # helper :"Foo::Bar"
123
+ # helper "foo/bar"
124
+ # helper :"foo/bar"
125
+ #
126
+ # The last two assume that <tt>"foo/bar".camelize</tt> returns "Foo::Bar".
127
+ #
128
+ # The method accepts a block too. If present, the block is evaluated in
129
+ # the context of the controller helper module. This simple call makes the
130
+ # +wadus+ method available in templates of the enclosing controller:
94
131
  #
95
- # # Multi-line
96
132
  # helper do
97
- # def foo(bar)
98
- # "#{bar} is the very best"
133
+ # def wadus
134
+ # "wadus"
99
135
  # end
100
136
  # end
101
137
  #
102
- # Finally, all the above styles can be mixed together, and the +helper+ method can be invoked with a mix of
103
- # +symbols+, +strings+, +modules+ and blocks.
138
+ # Furthermore, all the above styles can be mixed together:
104
139
  #
105
- # helper(:three, BlindHelper) { def mice() 'mice' end }
140
+ # helper FooHelper, "woo", "bar/baz" do
141
+ # def wadus
142
+ # "wadus"
143
+ # end
144
+ # end
106
145
  #
107
146
  def helper(*args, &block)
108
147
  modules_for_helpers(args).each do |mod|
109
- add_template_helper(mod)
148
+ next if _helpers.include?(mod)
149
+ _helpers_for_modification.include(mod)
110
150
  end
111
151
 
112
- _helpers.module_eval(&block) if block_given?
152
+ _helpers_for_modification.module_eval(&block) if block_given?
113
153
  end
114
154
 
115
155
  # Clears up all existing helpers in this class, only keeping the helper
@@ -123,72 +163,48 @@ module AbstractController
123
163
  default_helper_module! unless anonymous?
124
164
  end
125
165
 
126
- # Returns a list of modules, normalized from the acceptable kinds of
127
- # helpers with the following behavior:
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
166
+ # Given an array of values like the ones accepted by +helper+, this method
167
+ # returns an array with the corresponding modules, in the same order.
168
+ def modules_for_helpers(modules_or_helper_prefixes)
169
+ modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
170
+ case module_or_helper_prefix
164
171
  when Module
165
- arg
172
+ module_or_helper_prefix
173
+ when String, Symbol
174
+ helper_prefix = module_or_helper_prefix.to_s
175
+ helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
176
+ "#{helper_prefix}Helper".constantize
166
177
  else
167
178
  raise ArgumentError, "helper must be a String, Symbol, or Module"
168
179
  end
169
180
  end
170
181
  end
171
182
 
172
- private
173
- # Makes all the (instance) methods in the helper module available to templates
174
- # rendered through this controller.
175
- #
176
- # ==== Parameters
177
- # * <tt>module</tt> - The module to include into the current helper module
178
- # for the class
179
- def add_template_helper(mod)
180
- _helpers.module_eval { include mod }
183
+ def _helpers_for_modification
184
+ unless @_helpers
185
+ self._helpers = define_helpers_module(self, superclass._helpers)
186
+ end
187
+ _helpers
181
188
  end
182
189
 
183
- def default_helper_module!
184
- module_name = name.sub(/Controller$/, '')
185
- module_path = module_name.underscore
186
- helper module_path
187
- rescue MissingSourceFile => e
188
- raise e unless e.is_missing? "helpers/#{module_path}_helper"
189
- rescue NameError => e
190
- raise e unless e.missing_name? "#{module_name}Helper"
191
- end
190
+ private
191
+ def define_helpers_module(klass, helpers = nil)
192
+ # In some tests inherited is called explicitly. In that case, just
193
+ # return the module from the first time it was defined
194
+ return klass.const_get(:HelperMethods) if klass.const_defined?(:HelperMethods, false)
195
+
196
+ mod = Module.new
197
+ klass.const_set(:HelperMethods, mod)
198
+ mod.include(helpers) if helpers
199
+ mod
200
+ end
201
+
202
+ def default_helper_module!
203
+ helper_prefix = name.delete_suffix("Controller")
204
+ helper(helper_prefix)
205
+ rescue NameError => e
206
+ raise unless e.missing_name?("#{helper_prefix}Helper")
207
+ end
192
208
  end
193
209
  end
194
210
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/benchmarkable"
2
4
 
3
5
  module AbstractController
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AbstractController
2
4
  module Railties
3
5
  module RoutesHelpers
@@ -5,10 +7,26 @@ module AbstractController
5
7
  Module.new do
6
8
  define_method(:inherited) do |klass|
7
9
  super(klass)
8
- if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
9
- klass.send(:include, namespace.railtie_routes_url_helpers(include_path_helpers))
10
+
11
+ namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
12
+ actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
13
+
14
+ if namespace
15
+ klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
10
16
  else
11
- klass.send(:include, routes.url_helpers(include_path_helpers))
17
+ klass.include(routes.url_helpers(include_path_helpers))
18
+ end
19
+
20
+ # In the case that we have ex.
21
+ # class A::Foo < ApplicationController
22
+ # class Bar < A::Foo
23
+ # We will need to redefine _routes because it will not be correct
24
+ # via inheritance.
25
+ unless klass._routes.equal?(actual_routes)
26
+ klass.redefine_singleton_method(:_routes) { actual_routes }
27
+ klass.include(Module.new do
28
+ define_method(:_routes) { @_routes || actual_routes }
29
+ end)
12
30
  end
13
31
  end
14
32
  end
@@ -1,8 +1,9 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'action_view'
4
- require 'action_view/view_paths'
5
- require 'set'
1
+ # frozen_string_literal: true
2
+
3
+ require "abstract_controller/error"
4
+ require "action_view"
5
+ require "action_view/view_paths"
6
+ require "set"
6
7
 
7
8
  module AbstractController
8
9
  class DoubleRenderError < Error
@@ -17,66 +18,61 @@ module AbstractController
17
18
  extend ActiveSupport::Concern
18
19
  include ActionView::ViewPaths
19
20
 
20
- # Normalize arguments, options and then delegates render_to_body and
21
- # sticks the result in self.response_body.
22
- # :api: public
21
+ # Normalizes arguments, options and then delegates render_to_body and
22
+ # sticks the result in <tt>self.response_body</tt>.
23
23
  def render(*args, &block)
24
24
  options = _normalize_render(*args, &block)
25
- self.response_body = render_to_body(options)
26
- _process_format(rendered_format, options) if rendered_format
27
- self.response_body
25
+ rendered_body = render_to_body(options)
26
+ if options[:html]
27
+ _set_html_content_type
28
+ else
29
+ _set_rendered_content_type rendered_format
30
+ end
31
+ _set_vary_header
32
+ self.response_body = rendered_body
28
33
  end
29
34
 
30
35
  # Raw rendering of a template to a string.
31
36
  #
32
37
  # It is similar to render, except that it does not
33
- # set the response_body and it should be guaranteed
38
+ # set the +response_body+ and it should be guaranteed
34
39
  # to always return a string.
35
40
  #
36
- # If a component extends the semantics of response_body
37
- # (as Action Controller extends it to be anything that
41
+ # If a component extends the semantics of +response_body+
42
+ # (as ActionController extends it to be anything that
38
43
  # responds to the method each), this method needs to be
39
44
  # overridden in order to still return a string.
40
- # :api: plugin
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::TEXT
56
+ Mime[:text]
55
57
  end
56
58
 
57
- DEFAULT_PROTECTED_INSTANCE_VARIABLES = Set.new %w(
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
61
  # This method should return a hash with assigns.
64
62
  # You can overwrite this configuration per controller.
65
- # :api: public
66
63
  def view_assigns
67
- protected_vars = _protected_ivars
68
- variables = instance_variables
64
+ variables = instance_variables - _protected_ivars
69
65
 
70
- variables.reject! { |s| protected_vars.include? s }
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
- # Normalize args by converting render "foo" to render :action => "foo" and
77
- # render "foo/bar" to render :file => "foo/bar".
78
- # :api: plugin
79
- def _normalize_args(action=nil, options={})
71
+ private
72
+ # Normalize args by converting <tt>render "foo"</tt> to
73
+ # <tt>render :action => "foo"</tt> and <tt>render "foo/bar"</tt> to
74
+ # <tt>render :file => "foo/bar"</tt>.
75
+ def _normalize_args(action = nil, options = {}) # :doc:
80
76
  if action.respond_to?(:permitted?)
81
77
  if action.permitted?
82
78
  action
@@ -91,35 +87,40 @@ module AbstractController
91
87
  end
92
88
 
93
89
  # Normalize options.
94
- # :api: plugin
95
- def _normalize_options(options)
90
+ def _normalize_options(options) # :doc:
96
91
  options
97
92
  end
98
93
 
99
94
  # Process extra options.
100
- # :api: plugin
101
- def _process_options(options)
95
+ def _process_options(options) # :doc:
102
96
  options
103
97
  end
104
98
 
105
99
  # Process the rendered format.
106
- # :api: private
107
- def _process_format(format, options = {})
100
+ def _process_format(format) # :nodoc:
101
+ end
102
+
103
+ def _process_variant(options)
104
+ end
105
+
106
+ def _set_html_content_type # :nodoc:
107
+ end
108
+
109
+ def _set_vary_header # :nodoc:
110
+ end
111
+
112
+ def _set_rendered_content_type(format) # :nodoc:
108
113
  end
109
114
 
110
115
  # Normalize args and options.
111
- # :api: private
112
- def _normalize_render(*args, &block)
116
+ def _normalize_render(*args, &block) # :nodoc:
113
117
  options = _normalize_args(*args, &block)
114
- #TODO: remove defined? when we restore AP <=> AV dependency
115
- if defined?(request) && request && request.variant.present?
116
- options[:variant] = request.variant
117
- end
118
+ _process_variant(options)
118
119
  _normalize_options(options)
119
120
  options
120
121
  end
121
122
 
122
- def _protected_ivars # :nodoc:
123
+ def _protected_ivars
123
124
  DEFAULT_PROTECTED_INSTANCE_VARIABLES
124
125
  end
125
126
  end
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
4
+
1
5
  module AbstractController
2
6
  module Translation
7
+ mattr_accessor :raise_on_missing_translations, default: false
8
+
3
9
  # Delegates to <tt>I18n.translate</tt>. Also aliased as <tt>t</tt>.
4
10
  #
5
11
  # When the given key starts with a period, it will be scoped by the current
@@ -8,20 +14,23 @@ module AbstractController
8
14
  # <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
9
15
  # to translate many keys within the same controller / action and gives you a
10
16
  # simple framework for scoping them consistently.
11
- def translate(*args)
12
- key = args.first
13
- if key.is_a?(String) && (key[0] == '.')
14
- key = "#{ controller_path.tr('/', '.') }.#{ action_name }#{ key }"
15
- args[0] = key
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}"
16
24
  end
17
25
 
18
- I18n.translate(*args)
26
+ i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
27
+ I18n.translate(key, **options, raise: i18n_raise)
19
28
  end
20
29
  alias :t :translate
21
30
 
22
31
  # Delegates to <tt>I18n.localize</tt>. Also aliased as <tt>l</tt>.
23
- def localize(*args)
24
- I18n.localize(*args)
32
+ def localize(object, **options)
33
+ I18n.localize(object, **options)
25
34
  end
26
35
  alias :l :localize
27
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AbstractController
2
4
  # Includes +url_for+ into the host class (e.g. an abstract controller or mailer). The class
3
5
  # has to provide a +RouteSet+ by implementing the <tt>_routes</tt> methods. Otherwise, an
@@ -1,13 +1,16 @@
1
- require 'action_pack'
2
- require 'active_support/rails'
3
- require 'active_support/core_ext/module/attr_internal'
4
- require 'active_support/core_ext/module/anonymous'
5
- require 'active_support/i18n'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_pack"
4
+ require "active_support"
5
+ require "active_support/rails"
6
+ require "active_support/i18n"
6
7
 
7
8
  module AbstractController
8
9
  extend ActiveSupport::Autoload
9
10
 
11
+ autoload :ActionNotFound, "abstract_controller/base"
10
12
  autoload :Base
13
+ autoload :Caching
11
14
  autoload :Callbacks
12
15
  autoload :Collector
13
16
  autoload :DoubleRenderError, "abstract_controller/rendering"
@@ -17,4 +20,9 @@ module AbstractController
17
20
  autoload :Translation
18
21
  autoload :AssetPaths
19
22
  autoload :UrlFor
23
+
24
+ def self.eager_load!
25
+ super
26
+ AbstractController::Caching.eager_load!
27
+ end
20
28
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionController
4
+ module ApiRendering
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Rendering
9
+ end
10
+
11
+ def render_to_body(options = {})
12
+ _process_options(options)
13
+ super
14
+ end
15
+ end
16
+ end