ruby-on-rails 基于类的视图帮助器未按预期输出捕获的HTML

aiazj4mn  于 2023-04-08  发布在  Ruby
关注(0)|答案(1)|浏览(123)

我试图为我正在工作的一个项目创建一组视图帮助程序,由于它们共享许多公共代码,无论好坏,我试图采用面向对象的方法。然而,当我试图捕获和呈现HTML时,我遇到了问题。
它不是在标记中呈现HTML,而是在标记之前呈现HTML,并将其呈现为标记中的字符串。
我想知道为什么会有不同的行为,以及我能做些什么来修复它(如果有可能的话)

实施例1:工作职能法

我有以下助手:

# 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

在我的html.erb文件中,我有:

<%= my_helper('Summary text') do %>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
<% end %>

这将呈现:

<details>
  <summary>
    <span>
      Summary text
    </span>
  </summary>
  <div>
    <ul>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </div>
</details>

实施例2:非工作面向对象方法

在我的helper文件中,我定义了这个类:

# 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

在我的应用程序助手中,我有:

# application_helper.rb

def my_helper(summary_text, &block)
  MyHelper.new(summary_text).render(&block)
end

在我的html.erb文件中,我有:

<%= my_helper('Summary text') do %>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
<% end %>

这将呈现:

<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>

我希望面向对象的方法与基于函数的方法具有相同的结果。
我试过在Rails代码中调试这个问题,如果要我猜的话,我认为这与output_buffer和OO助手没有使用与视图相同的助手有关,但我不确定。

ffscu2ro

ffscu2ro1#

在这里,你要做的是将视图上下文传递给builder/decorator/presenter/view compont/thingamajigger,并调用它的方法:

# 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

相关问题