web-dev-qa-db-ja.com

Railsで異なるフォーマットの一部をレンダリングするにはどうすればよいですか?

HTMLを含むJSON応答を生成しようとしています。したがって、私は/app/views/foo/bar.json.erbを持っています:

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

/app/views/foo/_baz.html.erbをレンダリングしますが、/app/views/foo/_baz.json.erbのみをレンダリングします。 :format => 'html'を渡すことは役に立ちません。

112
James A. Rosen

roninekの応答 に基づいて、次のことが最善の解決策であることがわかりました。

/app/helpers/application.rb内:

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:

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

別の解決策は、renderを再定義して:formatパラメータ。

render :file地元の人々と一緒に仕事をするために、パスの不自由さなし。

29
James A. Rosen

Rails 3.2.3で始まり、render:partialを呼び出すとき(respond_toブロック)。

:formats => [:html]

の代わりに

:format => 'html'
99
Tim Haines

どうしたの

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

?私はこれをAtomビルダーテンプレート内からHTML ERBパーシャルをレンダリングしようとしましたが、うまく機能しました。グローバル変数をいじる必要はありません。それらが、それは彼らが何であるかです)。

きみの - with_format &block approach はクールですが、フォーマットのみを指定するという利点がありますが、単純なアプローチではテンプレートエンジン(ERB/builder/etc)も指定します。

64
Sam Stokes

Rails 3の場合、with_formatブロックは機能しますが、少し異なります。

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

Rails 4では、formatsパラメーターを渡すことができます。だからできる

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

Rails 3で同様のことができますが、その形式はサブ部分集合に渡されません(フォームが他の部分集合を呼び出す場合)。

Config/initializers/renderer.rbを作成することにより、Rails 3でRails 4の機能を使用できます。

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

http://railsguides.net/2012/08/29/Rails3-does-not-render-partial-for-specific-format/ を参照してください

31
DrewB

Rails 3)では、Viewにはformat配列があります。つまり、[:mobile、:html]を検索するように設定できます。デフォルトでは:mobileテンプレートを検索しますが、 :htmlテンプレートに戻ります。これを設定すると、内部パーシャルにカスケードされます。

これを設定するために見つけることができた最良の、しかしまだ欠陥のある方法は、この行を各モバイルテンプレート(パーシャルではない)の一番上に置くことでした。

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

欠点は、その行を複数のテンプレートに追加する必要があることです。 application_controller.rbから、これを一度設定する方法を知っている人がいれば、それを知りたいです。残念ながら、テンプレートはレイアウトの前にレンダリングされるため、モバイルレイアウトにその行を追加することはできません。

25

Zgchurchが書いたことについて詳しく説明します。

  • 例外を考慮に入れる
  • 呼び出されたブロックの結果を返す

役に立つかもしれないと思った。

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

次の2つのオプションがあります。

1)render :fileを使用します

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

2)@template_format変数を設定して、テンプレート形式をhtmlに変更します

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

「api/item.rabl」という名前のファイルがあり、それをHTMLビューからレンダリングしたいので、使用する必要がありました。

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

fileは、ファイル名にアンダースコアがないため、formats(およびパスと配列)ではなく、formatが含まれます)

5
Dorian

formatsオプションを渡すと、新しいRailsバージョン、少なくとも3.2で適切にレンダリングされるようです:

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

別のxml.builderビューファイルでXMLパーシャルをレンダリングしようとしたときに、このスレッドに出会いました。以下はそれを行う良い方法です

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

そしてええ...完全なファイル名もここで機能します...

1
Garfield