Fix rendering Action Text HTML in new threads
Because `ActionText::Content.renderer` is implemented as a `thread_cattr_accessor`, any default value set in the main thread will be inaccessible from other threads. Therefore, use a `cattr_accessor` to store the default renderer, and fall back to it when `renderer` has not been set by e.g. `with_renderer`. Fixes #40757.
This commit is contained in:
parent
9b6008924d
commit
ef61c9c8a3
|
@ -46,7 +46,7 @@ module ActionText
|
||||||
|
|
||||||
initializer "action_text.renderer" do
|
initializer "action_text.renderer" do
|
||||||
ActiveSupport.on_load(:action_text_content) do
|
ActiveSupport.on_load(:action_text_content) do
|
||||||
self.renderer = Class.new(ActionController::Base).renderer
|
self.default_renderer = Class.new(ActionController::Base).renderer
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[action_controller_base action_mailer].each do |abstract_controller|
|
%i[action_controller_base action_mailer].each do |abstract_controller|
|
||||||
|
|
|
@ -8,6 +8,7 @@ module ActionText
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
|
cattr_accessor :default_renderer, instance_accessor: false
|
||||||
thread_cattr_accessor :renderer, instance_accessor: false
|
thread_cattr_accessor :renderer, instance_accessor: false
|
||||||
delegate :render, to: :class
|
delegate :render, to: :class
|
||||||
end
|
end
|
||||||
|
@ -22,7 +23,7 @@ module ActionText
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(*args, &block)
|
def render(*args, &block)
|
||||||
renderer.render_to_string(*args, &block)
|
(renderer || default_renderer).render_to_string(*args, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,6 +116,15 @@ class ActionText::ContentTest < ActiveSupport::TestCase
|
||||||
assert_not defined?(::ApplicationController)
|
assert_not defined?(::ApplicationController)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "renders with layout when in a new thread" do
|
||||||
|
html = "<h1>Hello world</h1>"
|
||||||
|
rendered = nil
|
||||||
|
Thread.new { rendered = content_from_html(html).to_rendered_html_with_layout }.join
|
||||||
|
|
||||||
|
assert_includes rendered, html
|
||||||
|
assert_match %r/\A#{Regexp.escape '<div class="trix-content">'}/, rendered
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def content_from_html(html)
|
def content_from_html(html)
|
||||||
ActionText::Content.new(html).tap do |content|
|
ActionText::Content.new(html).tap do |content|
|
||||||
|
|
Loading…
Reference in New Issue