英文:
Class based view helper does not output captured HTML as expected
问题
对不起,我只能回答问题,而不能提供翻译。如果您有任何问题需要回答,请随时提问。
英文:
I am trying to create a set of view helpers for a project I am working in and as they share a lot of common code, for better or worse, I am trying to take an object oriented approach. However, I am having problems when I try to capture and render HTML.
Instead of rendering the HTML within the tag, it will render it before the tag and also render it as a string within the tag.
I want to understand why there are differences in the behaviour and what I can do to fix it (if it is even possible to)
Example 1: working functional approach
I have the following helper:
# application_helper.rb
def my_helper(summary_text, &block)
tag.details do
concat(tag.summary(tag.span(summary_text)))
concat(tag.div(&block))
end
end
In my html.erb file I have:
<%= my_helper('Summary text') do %>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<% end %>
This will render:
<details>
<summary>
<span>
Summary text
</span>
</summary>
<div>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
</details>
Example 2: non-working Object Oriented approach
In my helper file I have defined the class:
# helpers/my_helper.rb
require 'action_view'
class MyHelper
include ActionView::Context
include ActionView::Helpers
attr_reader :summary_text
def initialize(summary_text)
@summary_text = summary_text
end
def render(&block)
tag.details do
concat(tag.summary(tag.span(summary_text)))
concat(tag.div(&block))
end
end
end
And in my application helper I have:
# application_helper.rb
def my_helper(summary_text, &block)
MyHelper.new(summary_text).render(&block)
end
In my html.erb file I have:
<%= my_helper('Summary text') do %>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<% end %>
This will render:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<details>
<summary>
<span>
Summary text
</span>
</summary>
<div>
&lt;ul&gt;&lt;li&gt;Item 1&lt;/li&gt;&lt;li&gt;Item 2&lt;/li&gt;&lt;li&gt;Item 3&lt;/li&gt;&lt;/ul&gt;
</div>
</details>
I would expect the Object Oriented approach to have the same result as the functional based approach.
I've had a try at debugging this in the Rails code and if I were to have a guess I think it's something to do with the output_buffer
and the OO helper not using the same one as the view, but I am not sure.
答案1
得分: 1
你想要在这里做的是将视图上下文传递给构建器/装饰器/演示者/视图组件/什么东西,并在其上调用方法:
# 不要使用require - Rails组件已经通过railties加载
# 不要将其称为“Helper” - 这只会让事情更加混乱。
class ListBuilder
attr_reader :summary_text
attr_reader :context
delegate :tag, :concat, to: :context
def initialize(summary_text, context:)
@summary_text = summary_text
@context = context
end
def render(&block)
tag.details do
concat(tag.summary(tag.span(summary_text)))
concat(tag.div(&block))
end
end
end
def list_with_summary(summary_text, &block)
ListBuilder.new(summary_text, context: self).render(&block)
end
英文:
What you want to do here is pass the view context into the builder/decorator/presenter/view compont/thingamajigger and call the methods on it instead:
# do not use require - the Rails component are already loaded through railties
# do not call this "Helper" - that will just make things more confusing.
class ListBuilder
attr_reader :summary_text
attr_reader :context
delegate :tag, :concat, to: :context
def initialize(summary_text, context:)
@summary_text = summary_text
@context = context
end
def render(&block)
tag.details do
concat(tag.summary(tag.span(summary_text)))
concat(tag.div(&block))
end
end
end
def list_with_summary(summary_text, &block)
ListBuilder.new(summary_text, context: self).render(&block)
end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论