2010-08-24 117 views
86

當我渲染一個不存在的部分時,我得到一個異常。我想在呈現它之前檢查一個partial是否存在,如果它不存在,我會渲染其他東西。我做了我的.erb文件下面的代碼,但我覺得應該有一個更好的辦法來做到這一點:是否有任何Rails函數來檢查部分是否存在?

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

使用'rescue'是有風險的答案。在使用之前我會看看其他的解決方案。 – nertzy 2012-01-10 20:44:52

回答

89

目前,我用我的Rails以下3/3.1的項目:

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

的優勢Ø我見過的解決方案是,這將看所有的視圖路徑,而不是隻有你的rails根目錄。這對我來說很重要,因爲我有很多導軌引擎。

這也適用於Rails的4

+19

lookup_context.exists?('posts/find')也可以工作 – 2012-03-07 03:50:23

+7

lookup_context.exists?('posts/find')對我來說不起作用。相反,我使用lookup_context.exists?(名稱,前綴,部分)或lookup_content.exists?('find','posts',true)。 – Jenn 2012-06-12 17:30:57

+2

這是當前(rails> = 3.2)檢查模板的方法(source [apidock](http://apidock.com/rails/ActionView/LookupContext/ViewPaths/template_exists%3F)) – 2012-12-11 20:47:35

65

我這個太掙扎。這是我結束使用的方法:

<%= 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")) %> 
+5

我的問題是,我不想使用異常來做流控制,這是一種反模式:http://stackoverflow.com/questions/1546514/java-exceptions-as-control-flow – 2010-08-26 13:46:46

+6

異常是一種流量控制,用於處理超出程序正常運行的事件。如果動態部分應該在那裏,但是出現了問題,並且最終不會出現,那麼這對於例外來說是合理的使用(IMO當然 - 適當使用異常本身就是一場神聖的戰爭)。我會說你的選擇是檢查文件系統是否存在實際的文件。我會用該代碼更新我的答案。 – Jeff 2010-08-26 20:08:28

+3

我喜歡這個解決方案,但它會吞下部分中拋出的任何異常。恕我直言,這使得難以追查錯誤。 – Matt 2011-08-26 20:25:16

49

從視圖中,template_exists?工作,但調用約定不適用於單個部分名稱字符串,而是它需要template_exists?(名稱,前綴,部分)

檢查部分路徑: app/views/posts/_form.html .slim

用途:

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

On Rails 3.0.10我發現如果我有一個替代擴展名,比如app/views/posts/_foo.txt.erb,我需要將它添加到參數中:template_exists?(「foo.txt」,「posts 「,true) – 2011-10-27 22:25:35

+0

這在rails 3.2中已棄用 – 2012-12-11 20:45:51

+0

它似乎沒有在Rails 3.2.x中委派,但第二個參數是一個前綴數組。此外,它存在於電流控制器上。 – Brendan 2012-12-25 20:44:29

29

在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

+0

Upvoted。更新和更好地解釋參數。 – jacobsimeon 2013-10-15 16:21:39

+4

從一個視圖(如佈局),這個工作:'lookup_context.template_exists?(「navbar」,controller._prefixes,:partial)'。這告訴我當前渲染這個佈局的模板是否具有聲明的「navbar」部分,如果是,我可以渲染它。我通過':partial'來明確布爾是什麼 - ':partial'是truthy。感謝'_prefixes'位,@Flackou! – pdobb 2013-12-20 20:31:08

+0

如果您正在調用位於不同父目錄中的部分,請將'_prefixes'替換爲'nil'。 – ben 2015-05-01 19:39:58

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-10-19 20:32:28

+0

這正是我正在尋找的。非常乾淨的答案。 – Sunny 2016-03-03 16:20:38

+1

@BenPolinsky我想你可以使用'def render_if_exists(* args);渲染(*參數)如果...' – juanpastas 2017-04-17 15:31:47

5

我已經使用這個模式上取得了巨大成功多次:

<%= 
    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 
%> 

上面的代碼的好處是,我們可以處理拖車的具體情況:

  • 局部確實缺少
  • 局部存在,但它拋出一個錯誤出於某種原因

如果我們只是使用代碼<%= render :partial => "#{dynamic_partial}" rescue nil %>或一些衍生物,部分可能存在,但引發一個異常,它將被默默地吃掉,併成爲調試的痛苦之源。

1

你自己的助手什麼:

def render_if_exists(path, *args) 
    render path, *args 
rescue ActionView::MissingTemplate 
    nil 
end 
相關問題