actionpack 4.2.10 → 7.2.0.rc1

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 (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
1
5
  require "rails"
2
6
  require "action_controller"
3
7
  require "action_dispatch/railtie"
@@ -6,12 +10,20 @@ require "action_controller/railties/helpers"
6
10
  require "action_view/railtie"
7
11
 
8
12
  module ActionController
9
- class Railtie < Rails::Railtie #:nodoc:
13
+ class Railtie < Rails::Railtie # :nodoc:
10
14
  config.action_controller = ActiveSupport::OrderedOptions.new
15
+ config.action_controller.raise_on_open_redirects = false
16
+ config.action_controller.log_query_tags_around_actions = true
17
+ config.action_controller.wrap_parameters_by_default = false
11
18
 
19
+ config.eager_load_namespaces << AbstractController
12
20
  config.eager_load_namespaces << ActionController
13
21
 
14
- initializer "action_controller.assets_config", :group => :all do |app|
22
+ initializer "action_controller.deprecator", before: :load_environment_config do |app|
23
+ app.deprecators[:action_controller] = ActionController.deprecator
24
+ end
25
+
26
+ initializer "action_controller.assets_config", group: :all do |app|
15
27
  app.config.action_controller.assets_dir ||= app.config.paths["public"].first
16
28
  end
17
29
 
@@ -22,13 +34,25 @@ module ActionController
22
34
  initializer "action_controller.parameters_config" do |app|
23
35
  options = app.config.action_controller
24
36
 
25
- ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
26
- if app.config.action_controller[:always_permitted_parameters]
27
- ActionController::Parameters.always_permitted_parameters =
28
- app.config.action_controller.delete(:always_permitted_parameters)
29
- end
30
- ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
31
- (Rails.env.test? || Rails.env.development?) ? :log : false
37
+ ActiveSupport.on_load(:action_controller, run_once: true) do
38
+ ActionController::Parameters.permit_all_parameters = options.permit_all_parameters || false
39
+ if app.config.action_controller[:always_permitted_parameters]
40
+ ActionController::Parameters.always_permitted_parameters =
41
+ app.config.action_controller.always_permitted_parameters
42
+ end
43
+
44
+ action_on_unpermitted_parameters = options.action_on_unpermitted_parameters
45
+
46
+ if action_on_unpermitted_parameters.nil?
47
+ action_on_unpermitted_parameters = Rails.env.local? ? :log : false
48
+ end
49
+
50
+ ActionController::Parameters.action_on_unpermitted_parameters = action_on_unpermitted_parameters
51
+
52
+ unless options.allow_deprecated_parameters_hash_equality.nil?
53
+ ActionController::Parameters.allow_deprecated_parameters_hash_equality =
54
+ options.allow_deprecated_parameters_hash_equality
55
+ end
32
56
  end
33
57
  end
34
58
 
@@ -42,7 +66,7 @@ module ActionController
42
66
  options.javascripts_dir ||= paths["public/javascripts"].first
43
67
  options.stylesheets_dir ||= paths["public/stylesheets"].first
44
68
 
45
- # Ensure readers methods get compiled
69
+ # Ensure readers methods get compiled.
46
70
  options.asset_host ||= app.config.asset_host
47
71
  options.relative_url_root ||= app.config.relative_url_root
48
72
 
@@ -51,7 +75,20 @@ module ActionController
51
75
  extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
52
76
  extend ::ActionController::Railties::Helpers
53
77
 
54
- options.each do |k,v|
78
+ wrap_parameters format: [:json] if options.wrap_parameters_by_default && respond_to?(:wrap_parameters)
79
+
80
+ # Configs used in other initializers
81
+ filtered_options = options.except(
82
+ :default_protect_from_forgery,
83
+ :log_query_tags_around_actions,
84
+ :permit_all_parameters,
85
+ :action_on_unpermitted_parameters,
86
+ :always_permitted_parameters,
87
+ :wrap_parameters_by_default,
88
+ :allow_deprecated_parameters_hash_equality
89
+ )
90
+
91
+ filtered_options.each do |k, v|
55
92
  k = "#{k}="
56
93
  if respond_to?(k)
57
94
  send(k, v)
@@ -67,5 +104,46 @@ module ActionController
67
104
  config.compile_methods! if config.respond_to?(:compile_methods!)
68
105
  end
69
106
  end
107
+
108
+ initializer "action_controller.request_forgery_protection" do |app|
109
+ ActiveSupport.on_load(:action_controller_base) do
110
+ if app.config.action_controller.default_protect_from_forgery
111
+ protect_from_forgery with: :exception
112
+ end
113
+ end
114
+ end
115
+
116
+ initializer "action_controller.query_log_tags" do |app|
117
+ query_logs_tags_enabled = app.config.respond_to?(:active_record) &&
118
+ app.config.active_record.query_log_tags_enabled &&
119
+ app.config.action_controller.log_query_tags_around_actions
120
+
121
+ if query_logs_tags_enabled
122
+ app.config.active_record.query_log_tags |= [:controller] unless app.config.active_record.query_log_tags.include?(:namespaced_controller)
123
+ app.config.active_record.query_log_tags |= [:action]
124
+
125
+ ActiveSupport.on_load(:active_record) do
126
+ ActiveRecord::QueryLogs.taggings.merge!(
127
+ controller: ->(context) { context[:controller]&.controller_name },
128
+ action: ->(context) { context[:controller]&.action_name },
129
+ namespaced_controller: ->(context) {
130
+ if context[:controller]
131
+ controller_class = context[:controller].class
132
+ # based on ActionController::Metal#controller_name, but does not demodulize
133
+ unless controller_class.anonymous?
134
+ controller_class.name.delete_suffix("Controller").underscore
135
+ end
136
+ end
137
+ }
138
+ )
139
+ end
140
+ end
141
+ end
142
+
143
+ initializer "action_controller.test_case" do |app|
144
+ ActiveSupport.on_load(:action_controller_test_case) do
145
+ ActionController::TestCase.executor_around_each_request = app.config.active_support.executor_around_test_case
146
+ end
147
+ end
70
148
  end
71
149
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
1
5
  module ActionController
2
6
  module Railties
3
7
  module Helpers
@@ -5,7 +9,7 @@ module ActionController
5
9
  super
6
10
  return unless klass.respond_to?(:helpers_path=)
7
11
 
8
- if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
12
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
9
13
  paths = namespace.railtie_helpers_paths
10
14
  else
11
15
  paths = ActionController::Helpers.helpers_path
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController
6
+ # # Action Controller Renderer
7
+ #
8
+ # ActionController::Renderer allows you to render arbitrary templates without
9
+ # being inside a controller action.
10
+ #
11
+ # You can get a renderer instance by calling `renderer` on a controller class:
12
+ #
13
+ # ApplicationController.renderer
14
+ # PostsController.renderer
15
+ #
16
+ # and render a template by calling the #render method:
17
+ #
18
+ # ApplicationController.renderer.render template: "posts/show", assigns: { post: Post.first }
19
+ # PostsController.renderer.render :show, assigns: { post: Post.first }
20
+ #
21
+ # As a shortcut, you can also call `render` directly on the controller class
22
+ # itself:
23
+ #
24
+ # ApplicationController.render template: "posts/show", assigns: { post: Post.first }
25
+ # PostsController.render :show, assigns: { post: Post.first }
26
+ #
27
+ class Renderer
28
+ attr_reader :controller
29
+
30
+ DEFAULTS = {
31
+ method: "get",
32
+ input: ""
33
+ }.freeze
34
+
35
+ def self.normalize_env(env) # :nodoc:
36
+ new_env = {}
37
+
38
+ env.each_pair do |key, value|
39
+ case key
40
+ when :https
41
+ value = value ? "on" : "off"
42
+ when :method
43
+ value = -value.upcase
44
+ end
45
+
46
+ key = RACK_KEY_TRANSLATION[key] || key.to_s
47
+
48
+ new_env[key] = value
49
+ end
50
+
51
+ if new_env["HTTP_HOST"]
52
+ new_env["HTTPS"] ||= "off"
53
+ new_env["SCRIPT_NAME"] ||= ""
54
+ end
55
+
56
+ if new_env["HTTPS"]
57
+ new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
58
+ end
59
+
60
+ new_env
61
+ end
62
+
63
+ # Creates a new renderer using the given controller class. See ::new.
64
+ def self.for(controller, env = nil, defaults = DEFAULTS)
65
+ new(controller, env, defaults)
66
+ end
67
+
68
+ # Creates a new renderer using the same controller, but with a new Rack env.
69
+ #
70
+ # ApplicationController.renderer.new(method: "post")
71
+ #
72
+ def new(env = nil)
73
+ self.class.new controller, env, @defaults
74
+ end
75
+
76
+ # Creates a new renderer using the same controller, but with the given defaults
77
+ # merged on top of the previous defaults.
78
+ def with_defaults(defaults)
79
+ self.class.new controller, @env, @defaults.merge(defaults)
80
+ end
81
+
82
+ # Initializes a new Renderer.
83
+ #
84
+ # #### Parameters
85
+ #
86
+ # * `controller` - The controller class to instantiate for rendering.
87
+ # * `env` - The Rack env to use for mocking a request when rendering. Entries
88
+ # can be typical Rack env keys and values, or they can be any of the
89
+ # following, which will be converted appropriately:
90
+ # * `:http_host` - The HTTP host for the incoming request. Converts to
91
+ # Rack's `HTTP_HOST`.
92
+ # * `:https` - Boolean indicating whether the incoming request uses HTTPS.
93
+ # Converts to Rack's `HTTPS`.
94
+ # * `:method` - The HTTP method for the incoming request,
95
+ # case-insensitive. Converts to Rack's `REQUEST_METHOD`.
96
+ # * `:script_name` - The portion of the incoming request's URL path that
97
+ # corresponds to the application. Converts to Rack's `SCRIPT_NAME`.
98
+ # * `:input` - The input stream. Converts to Rack's `rack.input`.
99
+ #
100
+ # * `defaults` - Default values for the Rack env. Entries are specified in the
101
+ # same format as `env`. `env` will be merged on top of these values.
102
+ # `defaults` will be retained when calling #new on a renderer instance.
103
+ #
104
+ #
105
+ # If no `http_host` is specified, the env HTTP host will be derived from the
106
+ # routes' `default_url_options`. In this case, the `https` boolean and the
107
+ # `script_name` will also be derived from `default_url_options` if they were not
108
+ # specified. Additionally, the `https` boolean will fall back to
109
+ # `Rails.application.config.force_ssl` if `default_url_options` does not specify
110
+ # a `protocol`.
111
+ def initialize(controller, env, defaults)
112
+ @controller = controller
113
+ @defaults = defaults
114
+ if env.blank? && @defaults == DEFAULTS
115
+ @env = DEFAULT_ENV
116
+ else
117
+ @env = normalize_env(@defaults)
118
+ @env.merge!(normalize_env(env)) unless env.blank?
119
+ end
120
+ end
121
+
122
+ def defaults
123
+ @defaults = @defaults.dup if @defaults.frozen?
124
+ @defaults
125
+ end
126
+
127
+ # Renders a template to a string, just like
128
+ # ActionController::Rendering#render_to_string.
129
+ def render(*args)
130
+ request = ActionDispatch::Request.new(env_for_request)
131
+ request.routes = controller._routes
132
+
133
+ instance = controller.new
134
+ instance.set_request! request
135
+ instance.set_response! controller.make_response!(request)
136
+ instance.render_to_string(*args)
137
+ end
138
+ alias_method :render_to_string, :render # :nodoc:
139
+
140
+ private
141
+ RACK_KEY_TRANSLATION = {
142
+ http_host: "HTTP_HOST",
143
+ https: "HTTPS",
144
+ method: "REQUEST_METHOD",
145
+ script_name: "SCRIPT_NAME",
146
+ input: "rack.input"
147
+ }
148
+
149
+ DEFAULT_ENV = normalize_env(DEFAULTS).freeze # :nodoc:
150
+
151
+ delegate :normalize_env, to: :class
152
+
153
+ def env_for_request
154
+ if @env.key?("HTTP_HOST") || controller._routes.nil?
155
+ @env.dup
156
+ else
157
+ controller._routes.default_env.merge(@env)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController
6
+ module TemplateAssertions # :nodoc:
7
+ def assert_template(options = {}, message = nil)
8
+ raise NoMethodError,
9
+ 'assert_template has been extracted to a gem. To continue using it,
10
+ add `gem "rails-controller-testing"` to your Gemfile.'
11
+ end
12
+ end
13
+ end