パーシャルが存在するかどうかを確認するRails関数はありますか?


98

存在しないパーシャルをレンダリングすると、例外が発生します。レンダリングする前にパーシャルが存在するかどうかを確認したいのですが、存在しない場合は別のものをレンダリングします。.erbファイルで次のコードを実行しましたが、これを行うにはもっと良い方法があるはずです。

    <% begin %>
      <%= render :partial => "#{dynamic_partial}" %>
    <% rescue ActionView::MissingTemplate %>
      Can't show this data!
    <% end %>

1
を使用する答えrescueは危険です。使用する前に、他のソリューションを確認します。
Grant Hutchins

回答:


98

現在、私はRails 3 / 3.1プロジェクトで以下を使用しています。

lookup_context.find_all('posts/_form').any?

私が見た他のソリューションに対する利点は、これがレールのルートだけでなく、すべてのビューパスを調べることです。私はたくさんのレールエンジンを持っているので、これは私にとって重要です。

これはRails 4でも機能します。


9
lookup_context.exists?( 'posts / find')が機能しませんでした。代わりに、この例ではlookup_context.exists?(name、prefix、partial)またはlookup_content.exists?( 'find'、 'posts'、true)を使用しました。
Jenn

2
これは、テンプレート(ソースをチェックする方法現在の(> = 3.2レール)であるapidock
マセック

1
パーシャルが現在のビューテンプレートと同じフォルダーにある場合は、を使用できますlookup_context.exists?("find", lookup_context.prefixes, true)。この方法では、ビューディレクトリを呼び出しにハードコードする必要はありません。これはパーシャルのためのものであることに注意してください。部分的でない場合は、最後の引数を省略します(またはtrueの代わりにfalseを使用します)
Nathan Wallace

71

私もこれで苦労していました。これは私が最終的に使用した方法です:

<%= render :partial => "#{dynamic_partial}" rescue nil %>

基本的に、パーシャルが存在しない場合は何もしません。しかし、パーシャルが欠落している場合は何かを印刷しましたか?

編集1:ああ、私は読解に失敗します。あなたは何か他のものをレンダリングしたいと言っていました。その場合、これはどうですか?

<%= render :partial => "#{dynamic_partial}" rescue render :partial => 'partial_that_actually_exists' %>

または

<%= render :partial => "#{dynamic_partial}" rescue "Can't show this data!" %>

編集2:

代替方法:部分ファイルの存在を確認します。

<%= render :partial => "#{dynamic_partial}" if File.exists?(Rails.root.join("app", "views", params[:controller], "_#{dynamic_partial}.html.erb")) %>

6
私の質問は、アンチパターンである、私はフロー制御を行うために例外を使用したくないということです:stackoverflow.com/questions/1546514/...
ダニエルCukier

6
例外は、プログラムの通常の操作を超えて発生する処理に使用されるフロー制御の一種です。動的部分が存在するはずであるが、何かがうまくいかず、結果として存在しない場合、それは例外の妥当な使用法です(もちろん、IMO-例外の適切な使用はそれ自体が聖なる戦争です)。私はあなたの代わりは実際のファイルが存在するかどうかファイルシステムをチェックすることだと思います。そのコードで私の答えを更新します。
ジェフ

3
私はソリューションが好きですが、それでもパーシャルでスローされたあらゆる種類の例外を飲み込みます。私見これはエラーの追跡を難しくします。
マット

5
別のタイプの例外がある場合、rescue nilおよび... rescue ...メソッドはそれを非表示にします。これはデバッグが難しいバグにつながります。
nicholaides

8
私はこのソリューションが本当に嫌いです。救助は高価で、File.exists?パーシャルは1つの場所にのみ存在できると想定しています。lookup_contextを使用した@Reinのソリューションは、私が信じる方法です。
Bert Goethals

52

ビュー内から、template_exists?機能しますが、呼び出し規約は単一の部分的な名前の文字列では機能せず、代わりにtemplate_exists?(name、prefix、partial)を取ります

パスの一部を確認するには:app / views / posts / _form.html.slim

使用する:

lookup_context.template_exists?("form", "posts", true)

Rails 3.0.10では、app / views / posts / _foo.txt.erbのような代替の拡張機能がある場合、それを次のように引数に追加する必要があることがわかりました:template_exists?( "foo.txt"、 "posts" 、true)
Gabe Martin-Dempesy 2011年

これは、レール3.2で廃止されました
マセック

Rails 3.2.xでは委任されていないようですが、2番目の引数はプレフィックスの配列です。さらに、現在のコントローラー上に存在します。
ブレンダン

2
lookup_context.prefixesを2番目の引数として使用できます。lookup_context.template_exists?( "form"、lookup_context.prefixes、true)
lion.vollnhals

これは、ビューレイヤーからこの情報にアクセスするという点で、より良い答えです。
Brendon Muir

30

Rails 3.2.13では、コントローラーを使用している場合、これを使用できます。

template_exists?("#{dynamic_partial}", _prefixes, true)

template_exists?lookupcontextあなたが見ることができるように、に委任されていますAbstractController::ViewPaths

_prefixes コントローラの継承チェーンのコンテキストを提供します。

true パーシャルを探しているからです(通常のテンプレートが必要な場合は、この引数を省略できます)。

http://api.rubyonrails.org/classes/ActionView/LookupContext/ViewPaths.html#method-i-template_exists-3F


賛成。パラメータの最新かつより良い説明。
jacobsimeon 2013年

4
(レイアウトなどの)ビューから、これは機能しますlookup_context.template_exists?("navbar", controller._prefixes, :partial)。これにより、このレイアウトをレンダリングする現在のテンプレートに「navbar」パーシャルが指定されているかどうかがわかり、もしあれば、レンダリングできます。私:partialはそのブール値が何であるかを明確にするために単に:partial渡します- 真実です。_prefixesビットをありがとう、@ Flackou!
pdobb 2013

交換する_prefixesnil、あなたが別の親ディレクトリにそれの部分を呼び出している場合。
ベン

8

私はこれが答えられて、百万年前のものであることを知っていますが、これが私のためにこれを修正することになった方法です...

Rails 4.2

まず、これを私のapplication_helper.rbに入れます

  def render_if_exists(path_to_partial)
    render path_to_partial if lookup_context.find_all(path_to_partial,[],true).any?
  end

そして今、呼び出す代わりに

<%= render "#{dynamic_path}" if lookup_context.find_all("#{dynamic_path}",[],true).any? %>

私は電話するだけです <%= render_if_exists "#{dynamic_path}" %>

お役に立てば幸いです。(rails3では試していません)


1
フォールバックを提供する場合、これは機能しません。また、ローカル変数は考慮されません。
phillyslick、2015年

これはまさに私が探していたものです。とてもきれいな答え。
晴れた

1
私はあなたが使用できると仮定し@BenPolinsky def render_if_exists(*args); render(*args) if ...そのために
サイト

6

私は多くの場面でこのパラダイムを使用して大きな成功を収めてきました。

<%=
  begin
    render partial: "#{dynamic_partial}"
  rescue ActionView::MissingTemplate
    # handle the specific case of the partial being missing
  rescue
    # handle any other exception raised while rendering the partial
  end
%>

上記のコードの利点は、2つの特定のケースを処理できることです。

  • パーシャルは確かにありません
  • パーシャルは存在しますが、何らかの理由でエラーをスローしました

コード<%= render :partial => "#{dynamic_partial}" rescue nil %>または一部の派生物を使用する場合、パーシャルは存在する可能性がありますが、例外が発生します。これは黙って食べられ、デバッグの痛みの原因になります。


4

あなた自身のヘルパーはどうですか:

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.