Why is the block from the view displayed twice?

The web application that I am writing in Ruby on Rails has content panels that are used a lot. I am trying to write helpers to render these panels with a little clean syntax. I am not very familiar with writing helpers in the form of help, so this can be simple. However, when I try to use the "html" (erb code) passed to the helper in the block, I get strange results when the block is displayed twice.

The corresponding code is given below. This example uses ERB because I simplified it to avoid any possible problems with HAML, but I got the same result with HAML.

The HTML I want to do is:

<section class="panel panel-default">
  <header class="panel-heading">Contacts</header>

  <div class="panel-body">
    <p>Test</p>
  </div>
</section>

This is my assistant:

module ApplicationHelper
  def panel(type = :default, &block)
    tag = content_tag(:section, class: "panel panel-#{type.to_s}") do
      block.call PanelHelper.new
    end

    tag
  end

  class PanelHelper
    include ActionView::Helpers::TagHelper
    include ActionView::Context
    include ActionView::Helpers::CaptureHelper

    def header(text = nil, &block)
      if block_given?
        tag = content_tag(:header, block.call, class: 'panel-heading')
      elsif text
        tag = content_tag(:header, text, class: 'panel-heading')
      else
        raise ArgumentError, 'Either a block must be given, or a value must be provided for the text parameter.'
      end

      tag
    end

    def body(&block)
      content_tag(:div, block.call, class: 'panel-body')
    end
  end
end

It's my opinion:

<%= panel :default do |p| %>
  <%= p.header 'Contacts' %>
  <%= p.body do %>
    <p>Test</p>
  <% end %>
<% end %>

This is the HTML that is displayed:

<section class="panel panel-default">
  <header class="panel-heading">Contacts</header>

  <p>Test</p>
  <div class="panel-body">
    &lt;p&gt;Test&lt;/p&gt;
  </div>
</section>

, ? , , - .

, :

def body(&block)
  @helper.concat tag(:div, class: 'panel-body').html_safe
  block.call
  @helper.concat '</div>'.html_safe
end

@helper - PanelHelper ApplicationHelper. = p.body, .

+4
2

<% p.body do %>
  <p>Test</p>
<% end %> 

. <% p.body do %> <%= p.body %> <p>Test</p> .

EDIT:

def body(&block)
  content_tag :div, class: 'panel-body' do
    block.call
  end
end

<%= p.body do %>
  <p>Test</p>
<% end %> 

.

+1
<%= p.body do %>
  <p>Test</p>
<% end %>

, <p>Test</p> (), yield ( block.call) body ApplicationModule. railscast, , , auto HTML (I ' , , ).

, nil body:

def body(&block)
  content_tag(:div, block.call, class: 'panel-body')
  nil
end

, <p>Test</p> ( block.call, content_tag).

, block.call "<p>Test</p>"

def body(&block)
  content_tag(:div, "<p>Test</p>", class: 'panel-body')
  nil
end

, HTML . , yield/block.call , . <p>Test</p> .

, , @PrakashMurthy content_tag, ,

def body(&block)
  content_tag :div, class: 'panel-body' do
    block.call
  end
end

, , , yield, . capture, .

content_tag(:div, capture(&block), class: 'panel-body')
+1

Source: https://habr.com/ru/post/1569737/


All Articles