是否有任何Rails函数来检查部分是否存在?

是否有任何Rails函数来检查部分是否存在?

问题描述:

当我渲染一个不存在的部分时,我得到一个异常。我想在呈现它之前检查一个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

目前,我用我的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

我这个太挣扎。这是我结束使用的方法:

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

从视图中,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

在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

我知道这已经回答了,是一个亿岁,但在这里就是我结束了我解决这个...

的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

我已经使用这个模式上取得了巨大成功多次:

<%= 
    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 %>或一些衍生物,部分可能存在,但引发一个异常,它将被默默地吃掉,并成为调试的痛苦之源。

你自己的助手什么:

def render_if_exists(path, *args) 
    render path, *args 
rescue ActionView::MissingTemplate 
    nil 
end