Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discrepancy when capturing Rails view block

I have an ERB view with two blocks:

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

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

where test_h1 and test_h2 are similar helpers, but one is defined in a helper file, while another via helper_method in a controller:

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 produces the expected result and test_h2 renders the inner template block first:

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

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

Why? What would be an idiomatic way to write test_h2 ?

like image 822
Alexander Azarov Avatar asked Dec 14 '18 10:12

Alexander Azarov


2 Answers

I think both examples of views should be re-written as:

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

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

My understanding that '<%=' forces to render the output of the block to the output stream, that was not an intended behavior in these two examples

like image 66
Aleksey Studnev Avatar answered Nov 03 '22 16:11

Aleksey Studnev


capture overrides current output buffer and just calls the block (which is still bound to other view context), thus override has no effect when called from controller because view_context is not the same context the view is being rendered in.

To work around contexts you can define your helper like so:

# in controller
helper 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
like image 2
Vasfed Avatar answered Nov 03 '22 16:11

Vasfed