Rails'de farklı bir biçimin bir kısmını nasıl oluştururum?


115

Bazı HTML içeren bir JSON yanıtı oluşturmaya çalışıyorum. Böylece, elimde /app/views/foo/bar.json.erb:

{
  someKey: 'some value',
  someHTML: "<%= h render(:partial => '/foo/baz') -%>"
}

Ben render etmesini istiyorum /app/views/foo/_baz.html.erbama sadece render edecek /app/views/foo/_baz.json.erb. Pas vermek :format => 'html'yardımcı olmuyor.


Soru başlığı James'in özel probleminden çok daha geneldir. Başka çözümler arıyorsanız, buraya bir göz atın: stackoverflow.com/questions/7616097/…
miguelsan

Yanıtlar:


101

Rails 3.2.3 ile başlayarak, render çağırırken: kısmi (yalnızca respond_tobloğun dışında çalışır ).

render formats: [ :html ]

onun yerine

render format: 'html'

Sanırım bağlama bağlı olarak farklı "en iyi" yanıtlar olabilir, bu nedenle bu soruya anlamlı bir şekilde oy vermek zor, ancak bu, bir :formatseçeneğin olacağını umduktan sonra bir RJS içinden aynı addan bir HTML şablonunu kolayca oluşturma ihtiyacımı karşıladı iş. Teşekkürler!
ches

1
Bu aynı zamanda Rails 5.0.2 için de geçerlidir. Bununla birlikte, :content_typebazı durumlarda seçeneği de belirtmeniz gerekebileceğini unutmayın - örneğin, bir format.pdfblok içinden bir HTML şablonunun oluşturulması yalnızca ile yapılabilir render "template", formats: [:html], content_type: "text/html". Buna ihtiyacım var çünkü kitaplarımın örneklerinin yalnızca e-posta listemin üyeleri için doğrudan indirilmesine izin veriyorum - bunun yerine normal ziyaretçiler bir kayıt formu alıyor.
Michael Trojanek

64

Sorun ne

render :partial => '/foo/baz.html.erb'

? Bunu bir Atom oluşturucu şablonunun içinden kısmi bir HTML ERB oluşturmak için denedim ve iyi çalıştı. Global değişkenlerle uğraşmak gerekmez (evet, önlerinde "@" olduğunu biliyorum, ama öyleler).

Kişisel with_format &blockyaklaşım olsa serin ve sıra basit yaklaşım şablon motorunu belirtir oysa sadece, biçimi belirtmek avantajı (ERB / inşaatçı / vs) vardır.


26
Bunun tek dezavantajı, eğer kısmi render diğer kısımları işlerse, siz girip tüm kısmi render çağrılarınızı isimlerine ".html.erb" içerecek şekilde değiştirmediğiniz sürece başarısız olacaktır.
chrisrbailey

4
bunun çalışması için şablon oluşturma motorunu belirtmeniz gerekmez. (En az raylar kadar 3). Aşağıdakiler gayet iyi çalışıyor: render (: partial => "baz.html")
Tim Harper

1
Eğer farklı yerel için farklı partials (örn varsa Çalışmaz baz.en.html.erb, baz.fr.html.erb) ve istediğiniz render :partial(, yedekleri ile vs) ler doğru bir tercih için mantık.
John

1
Raylar 3.2.3 itibariyle, bu çözümü kullanırken aşağıdaki uyarıyı görüyorum:DEPRECATION WARNING: Passing a template handler in the template name is deprecated. You can simply remove the handler name or pass render :handlers => [:erb] instead.
YWCA Merhaba

3
Bu yaklaşımın bir dezavantajı, foo.baz.html.[your_string]bunun yerine yerelleştirmelerin arayacağıdır foo.baz.[your_string]. zgchurc'un cevabı daha iyi bir çözüm.
mbillard

32

Rails 3 için with_format bloğu çalışır, ancak biraz farklıdır:

  def with_format(format, &block)
    old_formats = formats
    self.formats = [format]
    block.call
    self.formats = old_formats
    nil
  end

3.2.0 raylarla da çalışır :)
gucki

32

Rails 4, bir format parametresi geçirmenize izin verecektir. Böylece yapabilirsin

render(:partial => 'form', :formats => [:html])} 

Rails 3'te benzer bir şey yapabileceğinizi, ancak bu formatı herhangi bir alt parçaya geçirmeyeceğini unutmayın (form diğer parçaları çağırırsa).

Config / initializers / renderer.rb oluşturarak Rails 3'te Rails 4 yeteneğine sahip olabilirsiniz:

class ActionView::PartialRenderer
  private
  def setup_with_formats(context, options, block)
    formats = Array(options[:formats])
    @lookup_context.formats = formats | @lookup_context.formats
    setup_without_formats(context, options, block)
  end

  alias_method_chain :setup, :formats
end

Bkz. Http://railsguides.net/2012/08/29/rails3-does-not-render-partial-for-specific-format/


garip, neden bir Rails 3.2.19 uygulamasında benim için çalışmadığını merak ediyorum, uygulamamdaki farkı neyin yarattığını merak ediyorum. ActionView render'ı alınamıyor: formatlara saygı duymak için kısmi argüman, bu yama ile bile hiçbir fark yaratmıyor gibi görünüyor.
jrochkind

29

Bina roninek tepki , ben şu olmak için en iyi çözüm bulduk:

/app/helpers/application.rb içinde:

def with_format(format, &block)
  old_format = @template_format
  @template_format = format
  result = block.call
  @template_format = old_format
  return result
end

/App/views/foo/bar.json içinde:

<% with_format('html') do %>
  <%= h render(:partial => '/foo/baz') %>
<% end %>

Alternatif bir çözüm, renderkabul etmek için yeniden tanımlamak olabilir.:format parametreyi .

Ben alamadım render :filehalk ile ve bazı yol wonkiness olmadan çalışmak.


8
benim zevklerime göre fazla hilekâr. Tüm uzantıyı belirtmek daha iyidir.
Tim Harper

1
Raylar 3 için zgchurch'ün cevabına bakın.
lillq

25

Rails 3'te, Görünümün bir biçimler dizisi vardır, bu da onu [: mobile,: html] aramasını ayarlayabileceğiniz anlamına gelir. Varsayılan olarak aranacak ayar: mobil şablonlar, ancak geri dönüler: html şablonları. Bunu ayarlamanın etkileri, iç kısımlara doğru kademeli hale gelecektir.

Bunu ayarlamanın bulabildiğim en iyi, ancak yine de kusurlu yolu, bu satırı her tam mobil şablonun en üstüne koymaktı (ancak kısmi değil).

<% self.formats = [:mobile, :html] %>

Kusur, bu satırı birden çok şablona eklemeniz gerektiğidir. Bunu bir kez, application_controller.rb'den ayarlamanın bir yolunu bilen varsa, bunu bilmek isterim. Ne yazık ki, bu satırı mobil düzeninize eklemek işe yaramıyor, çünkü şablonlar düzenden önce işleniyor.


Bunu açıkladığınız için teşekkürler. Onu başka bir yerde kullandım: stackoverflow.com/questions/47459724/…
Joshua Pinter

16

Sadece zgchurch'ün yazdıklarını detaylandırarak:

  • istisnaları hesaba katmak
  • çağrılan bloğun sonucunu döndürmek

Faydalı olabileceğini düşündüm.

def with_format(format, &block)
  old_formats = formats
  begin
    self.formats = [format]
    return block.call
  ensure
    self.formats = old_formats
  end
end

10

İki seçeneğiniz var:

1) kullanım render :file

render :file => "foo/_baz.json.erb"

2) @template_format değişkenini ayarlayarak şablon formatını html olarak değiştirin

<% @template_format = "html" %>
<%= h render(:partial => '/foo/baz') %>

1
<% @template_format = "html"%> benim için çalıştı, çünkü kısmen yüklenmiş diğer parçalarım zincirdeki diğer renderları güncellemem gerekmedi.
pagetribe

5

'Api / item.rabl' adında bir dosyam vardı ve bunu bir HTML görünümünden oluşturmak istedim, bu yüzden şunu kullanmak zorundaydım:

render file: 'api/item', formats: [:json]

( fileçünkü dosyanın adında alt çizgi yoktur formatsve yoktur format(ve geçer ve dizi))


2

Görünüşe göre bir formatsseçeneğin geçilmesi onu daha yeni Rails sürümünde düzgün şekilde işleyecektir, en az 3.2:

{
  someKey: 'some value',
  someHTML: "<%= h render('baz', formats: :html) -%>"
}

1

Başka bir xml.builder görünüm dosyasında bir XML parçasını oluşturmaya çalışırken bu iş parçacığıyla karşılaştım. Takip etmenin güzel bir yolu

xml.items :type => "array" do
    @items.each do |item|
        xml << render(:partial => 'shared/partial.xml.builder', :locals => { :item => item })
    end
end

Ve evet ... Tam dosya adı burada da çalışıyor ...


Bu, @chrisrbailey'nin başka bir cevapta bahsettiği aynı iç-kısmi-problemden muzdariptir: eğer tam bir dosya adı ile aradığınız kısmın kendisi kısmîler kullanıyorsa (her biri için tam dosya adını belirtmeden), başarısız olacaktır.
James A. Rosen
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.