Расхождение при захвате Rails view block

У меня есть вид ERB с двумя блоками:

<%= test_h1 do %>
  <%= 'test1' %>
<% end -%>

<%= test_h2 do %>
  <%= 'test2' %>
<% end -%>

где test_h1 и test_h2 являются похожими помощниками, но один определяется в файле помощника, а другой - через helper_method в контроллере:

module TestHelper
  def test_h1(&block)
    link_to '/url' do
      capture(&block)
    end
  end
end

class TestController < ApplicationController
  helper_method :test_h2

  def test_h2(&block)
    helpers.link_to '/url' do
      helpers.capture(&block)
    end
  end
end

test_h1 выдает ожидаемый результат, а test_h2 визуализирует внутренний блок шаблона:

<a href="/url">test1</a>

test2<a href="/url"></a>

Зачем? Каков был бы идиоматический способ написать test_h2?

6
14 дек. '18 в 13:43
источник поделиться
4 ответов

При использовании capture с вашего контроллера, вывод добавляется в буфер страницы, в результате чего <%= от вашего erb выводится сразу на вывод страницы.

Чтобы обойти это, вам нужно использовать <% вместо этого в вашем блоке test_h2. Таким образом, чтобы получить ожидаемое поведение в обоих случаях, используйте этот синтаксис:

<%= test_h1 do %>
  <%= 'test1' %>
<% end -%>

<%= test_h2 do %>
  <% 'test2' %>
<% end -%>

Больше информации в этой статье: https://thepugautomatic.com/2013/06/helpers/

2
17 дек. '18 в 22:17
источник

Я думаю, что оба примера взглядов должны быть переписаны как:

<%= test_h1 do %>
  <% 'test1' %>
<% end -%>

<%= test_h2 do %>
  <% 'test2' %>
<% end -%>

Насколько я понимаю, "<% =" вынуждает выводить блок в выходной поток, что не было предполагаемым поведением в этих двух примерах

2
14 дек. '18 в 23:52
источник

capture переопределяет текущий выходной буфер и просто вызывает блок (который все еще связан с другим контекстом представления), таким образом, переопределение не имеет никакого эффекта при вызове из контроллера, потому что view_context не тот же контекст, в котором визуализируется представление.

Чтобы обойти контексты, вы можете определить своего помощника следующим образом:

# in controller
_helpers.module_eval do
  def test_h3(&block)
    # this will run in view context, so call 'controller.some_func' to access controller instance
    link_to '/url' do
      capture(&block)
    end
  end
end
0
21 дек. '18 в 15:16
источник

Идематический способ сделать это в рельсах - переместить метод test_h2 в задачу и включить ее в контроллер, а также в класс помощников.

Или определите test_h2 как helper_method в вашем классе контроллера.

Но, как правило, методы, которые необходимы в нескольких местах, должны быть поставлены под сомнение и включать те проблемы, где это необходимо.

Также, если вам нужны методы для представлений, включите проблемы или определите свои собственные методы внутри помощников.

См. Можем ли мы вызвать метод контроллера из представления (как мы в идеале вызываем из помощника)?
Как использовать проблемы в Rails 4

-1
16 дек. '18 в 17:27
источник

Посмотрите другие вопросы по меткам или Задайте вопрос