Raylar blokla kısmi render


119

Panel stilini sağlayan yazdığım bir html bileşenini yeniden kullanmaya çalışıyorum. Gibi bir şey:

  <div class="v-panel">
    <div class="v-panel-tr"></div>
    <h3>Some Title</h3>
    <div class="v-panel-c">
      .. content goes here
    </div>
    <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
  </div>

Görüyorum ki render işlemi bir blok alıyor. O zaman şöyle bir şey yapabileceğimi düşündüm:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title %></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
  <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
</div>

Ve şöyle bir şey yapmak istiyorum:

#some html view
<%= render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
  <p>Here is some content to be rendered inside the panel</p>
<% end %>

Maalesef bu, bu hatayla çalışmaz:

ActionView::TemplateError (/Users/bradrobertson/Repos/VeloUltralite/source/trunk/app/views/sessions/new.html.erb:1: , unexpected tRPAREN

old_output_buffer = output_buffer;;@output_buffer = '';  __in_erb_template=true ; @output_buffer.concat(( render :partial => '/shared/panel', :locals => {:title => "Welcome"} do ).to_s)
on line #1 of app/views/sessions/new.html.erb:
1: <%= render :partial => '/shared/panel', :locals => {:title => "Welcome"} do -%>
...

Yani =açıkça bir bloğa sahip olanı sevmiyor , ama eğer onu kaldırırsam, o zaman herhangi bir çıktı vermiyor.

Burada başarmaya çalıştığım şeyi nasıl yapacağını bilen var mı? Bu panel html'sini sitemin birçok yerinde yeniden kullanmak istiyorum.


1
Kabul edilen cevap doğrudur, ancak Rails layout5.0.0'dan beri, bu- geçici çözüm olmadan mümkündür , bkz. Guides.rubyonrails.org/…
fabi

Yanıtlar:


208

Yukarıdaki yanıtların her ikisi de işe yarasa da (yine de Tony'nin bağlantı kurduğu örnek), yukarıdaki yazıda en kısa yanıtı buldum (Kornelis Sietsma'nın yorumu)

Ben tahmin render :layoutyapar tam olarak ben aradığımı:

# Some View
<%= render :layout => '/shared/panel', :locals => {:title => 'some title'} do %>
  <p>Here is some content</p>
<% end %>

ile kombine:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title -%></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
</div>

6
Rails 3.2.2'de, <%= %>bunun yerine kullanmanız gerektiğini düşünüyorum <% %>, örneğin<%= render :layout => '/shared/panel',
Siwei Shen 申思维

haklısın, bu gönderi Rails versiyonu hakkında hiçbir varsayımda bulunmuyor, eminim insanlar bunu anlayabilirler.
brad

bunun gibi (problemimi çözer, yani +1), ama bu iyi bir uygulama mı? nedense biraz yavaşlama olmayacak mı? Belki de veritabanı, başka bir verim nedeniyle sandığından daha erken tetikleniyor (şimdi bunu tek başıma araştırmak için zamanım yok, sadece merak ediyorum)
eşdeğer8

1
Bir içeriğin verilip verilmediğini bilmenin bir yolu var mı? İsteğe bağlı olması durumunda.
Vadorequest

3
Rails 5.0'da bir değişiklik vardı, bu nedenle bu yalnızca düzenler için değil, tüm parçalar için geneldir. Arama kodunun ilk satırını şu şekilde değiştirebilirsiniz:<%= render '/shared/panel', title: 'some title' do %>
Jay Mitchell

27

İşte önceki cevaplara dayalı bir alternatif.

Parçanızı oluşturun shared/_modal.html.erb:

<div class="ui modal form">
  <i class="close icon"></i>
  <div class="header">
    <%= heading %>
  </div>
  <div class="content">
    <%= capture(&block) %>
  </div>
  <div class="actions">
    <div class="ui negative button">Cancel</div>
    <div class="ui positive button">Ok</div>
  </div>
</div>

Yönteminizi şurada tanımlayın application_helper.rb:

def modal_for(heading, &block)
  render(
    partial: 'shared/modal',
    locals: { heading: heading, block: block }
  )
end

Herhangi bir görünümden arayın:

<%= modal_for('My Title') do |t| %>
  <p>Here is some content to be rendered inside the partial</p>
<% end %>

11

Yakalama yardımcısını ve hatta render çağrısında satır içi olarak kullanabilirsiniz:

<%= render 'my_partial',
           :locals => { :title => "Some Title" },
           :captured => capture { %>
    <p>Here is some content to be rendered inside the partial</p>
<% } %>

ve paylaşımlı / panelde:

<h3><%= title %></h3>
<div class="my-outer-wrapper">
  <%= captured %>
</div>

hangisi üretecek:

<h3>Some Title</h3>
<div class="my-outer-wrapper">
  <p>Here is some content to be rendered inside the partial</p>
</div>

Bkz. Http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html


1
Satır içi desen, birden fazla bloğa kısmen ihtiyaç duyan bir şey için iyidir.
mahemoff

4

Kabul edilen cevaba göre, bu benim için Rails 4 kullanarak iyi sonuç verdi.

Bir paneli şu şekilde oluşturabiliriz:

= render_panel('Non Compliance Reports', type: 'primary') do
  %p your content goes here!

görüntü açıklamasını buraya girin

Bu, bir yardımcı yöntem ve paylaşılan bir görünüm gerektirir:

yardımcı yöntem (ui_helper.rb)

def render_panel(heading, options = {}, &block)
  options.reverse_merge!(type: 'default')
  options[:panel_classes] = ["panel-#{options[:type]}"]

  render layout: '/ui/panel', locals: { heading: heading, options: options } do
    capture(&block)
  end
end

Görüntüle (/ui/panel.html.haml)

.panel{ class: options[:panel_classes] }
  .panel-heading= heading
  .panel-body
    = yield

Bu, Rails 5.x'te de çalışıyor, sadece değiştirmem panel.html.hamlgerekiyor_panel.html.haml
Kris

1

Önce bir değişkene atayıp sonra çıktı verirseniz işe yarayacağını düşünüyorum (sadece hızlı kirli test yaptım).

<% foo = render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
<p>Here is some content to be rendered inside the panel</p>
<% end %>
<%= foo %>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.