Railsで別のフォーマットのパーシャルをレンダリングするにはどうすればよいですか?


114

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'しても役に立たない。


質問のタイトルは、ジェームズの特定の問題よりもはるかに一般的です。あなたは他のソリューションを探している場合は、ここで見てみましょう:stackoverflow.com/questions/7616097/...
miguelsan

回答:


100

Rails 3.2.3から、render:partialを呼び出す場合(respond_toブロックの外側でのみ機能)。

render formats: [ :html ]

の代わりに

render format: 'html'

私はコンテキストに応じて異なる「最良の」回答があるかもしれないと思うので、この質問に意味のある賛成票を投じることは難しいですが、これは、:formatオプションが期待される後、同じ名前のRJSからHTMLテンプレートを簡単にレンダリングする私のニーズを満たしました作業。ありがとう!
2013年

1
これはRails 5.0.2でも機能します。ただし、:content_typeオプションを指定する必要がある場合もあります。たとえば、format.pdfブロック内からのHTMLテンプレートのレンダリングは、でのみ実行できrender "template", formats: [:html], content_type: "text/html"ます。これが必要なのは、私のメーリングリストのメンバーだけが自分の本のサンプルを直接ダウンロードできるためです。通常の訪問者は、代わりに登録フォームを受け取ります。
Michael Trojanek 2017年

64

どうしたの

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

?Atomビルダーテンプレート内からHTML ERBパーシャルをレンダリングするためにこれを試したところ、うまくいきました。グローバル変数をいじる必要はありません(ええ、私はそれらの前に "@"が付いていることを知っていますが、それがそうです)。

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


26
これの唯一の欠点は、パーシャルが他のパーシャルをレンダリングする場合に、パーシャルレンダリングのすべての呼び出しを変更して名前に「.html.erb」を含めるように変更しない限り失敗することです。
chrisrbailey 2009

4
これを機能させるためにテンプレートエンジンを指定する必要はありません。(少なくともレール3以降)。次のコードは問題なく機能します。render(:partial => "baz.html")
Tim Harper

1
ロケールごとに異なるパーシャル(たとえばbaz.en.html.erbbaz.fr.html.erb)がありrender :partial、適切なロケールを選択するためのロジック(フォールバックなど)が必要な場合は機能しません。
ジョン

1
このソリューションを使用する際に、レール3.2.3のように、私は次の警告を見ている: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こんにちは

3
このアプローチの欠点の1つは、ローカリゼーションがのfoo.baz.html.[your_string]代わりに検索することですfoo.baz.[your_string]。zgchurcの答えはより良い解決策です。
mbillard 2012

32

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

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

レール3.2.0でも動作します:)
gucki 2012年

32

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/を参照してください


奇妙なことに、なぜそれがRails 3.2.19アプリで機能しないのか、アプリの違いは何なのかと思います。このパッチを使用しても、:formats引数を尊重するためにActionView render:partialを取得できません。まったく違いがないようです。
jrochkind 2014年

29

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地元の人たちと一緒に仕事をすることができず、いくつかの道の乱れがありませんでした。


8
私の好みにはハックしすぎる。拡張子全体を指定することをお勧めします。
Tim Harper、

1
Rails 3については、zgchurchの回答を参照してください。
lillq 2010

25

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

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

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

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


説明していただきありがとうございます。私は他の場所でそれを使用してしまいました:stackoverflow.com/questions/47459724/…–
Joshua Pinter

16

zgchurchが書いたものについて詳しく説明します。

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

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

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

10

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

1)使用 render :file

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

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

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

1
<%@template_format = "html"%>は私にとってはうまくいきました。パーシャルをロードした他のパーシャルがチェーンの下の他のレンダーを更新する必要がないためです。
pagetribe 2011年

5

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

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

fileファイル名ためにはアンダースコアを持っていない、formatsとしないformat)(と通過し、アレイ)


2

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

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

1

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

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

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


これは、@ chrisrbaileyが別の回答で述べたものと同じinner-partials-problemの影響を受けます。完全なファイル名で呼び出す部分自体が部分的なものを使用する場合(それぞれに完全なファイル名を指定せずに)、失敗します。
James
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.