Рендеринг партиала с разными блоками контента на одной странице: мне нужен частичный помощник, который принимает блок контента

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

=container($class)
  .#{$class}.container
    .container-inner
      @content

+container(header)
  foo: bar

+container(main)
  baz: quux

Результирующий CSS:

.header.container .container-inner {
  foo: bar;
}

.main.container .container-inner {
  baz: quux;
}

Я пытаюсь сделать то же самое с частями Падрино/Мидлмена. Проблема в том, что партиалы не принимают блоки контента (почему?). :(

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

Частичное partials/container.haml:

.container
  = yield_content :container

Страница index.html.haml:

- content_for :container do
  Foo

= partial('partials/container')


- content_for :container do
  Bar

= partial('partials/container')

Результирующий HTML:

<div class="container">
  Foo
</div>
<div class="container">
  Foo
  Bar
</div>

Как видите, он дублирует мой контент, что абсолютно неприемлемо. Кроме того, этот способ не позволяет предоставлять аргументы, которые будут использоваться для настройки HTML-оболочки.

Поэтому я подумал о создании помощника. Это позволило бы использовать следующий стиль использования, который более элегантен, чем content_for, а также поддерживает передачу переменных в блок контента:

= partial_with_content_block('partials/container', class: 'header') do
  Foo

= partial_with_content_block('partials/container', class: 'main') do
  Bar

Как мне реализовать такой помощник?


person Andrey Mikhaylov - lolmaus    schedule 08.11.2013    source источник


Ответы (2)


Что-то вроде этого должно работать, но я пропустил часть:

def container(options={}, &block)
  raise ArgumentError, "Missing block" unless block_given?
  content = capture_html(&block)
  content_tag(:div, content, options)
end

Звонить как:

= container(class: 'main') do
  p More content here

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

= content_tag :div, class: 'main' do
  p More content
person zwippie    schedule 08.11.2013
comment
Хорошо, я поторопился, предположив, что это Rails. Но похоже, что у Миддлмана есть метод content_tag, который вы можете использовать. block_given? — это простой метод Ruby, поэтому я думаю, что он будет работать в Middleman. Изменить: кроме capture... - person zwippie; 08.11.2013
comment
Спасибо @zwippie, я не заметил метод content_tag. Моя оболочка контейнера состоит из двух элементов-оболочек, поэтому ваш вспомогательный пример очень полезен. Я отредактировал ваш ответ, чтобы он полностью соответствовал Падрино/Мидлмену. - person Andrey Mikhaylov - lolmaus; 09.11.2013
comment
Пожалуйста. Я никогда не знал, что уровень представления Padrino/Middleman получил столько достоинств от Rails (не так ли?). Выглядит интересно. - person zwippie; 10.11.2013

Частицы посредника принимают блоки контента, но синтаксис немного отличается. ERB приведен ниже, но вы сможете сделать это и в HAML.

<% partial 'my_partial' do %>
    My Content
<% end %>

my_partial.html.erb

<p>
    <%= yield %>
</p>

Результат

<p>
    My Content
</p>
person Jimothy    schedule 07.12.2015
comment
Сначала я сказал, что вы должны использовать render_partial, но это не так. render_partial — это просто псевдоним для partial, так что любой из них будет работать. - person Jimothy; 08.12.2015