102

当我渲染一个不存在的部分时,我得到一个异常。我想在渲染之前检查一个部分是否存在,如果它不存在,我会渲染别的东西。我在我的 .erb 文件中做了以下代码,但我认为应该有更好的方法来做到这一点:

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

8 回答 8

102

目前,我在 Rails 3/3.1 项目中使用以下内容:

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

与我见过的其他解决方案相比,优势在于这将查看所有视图路径,而不仅仅是您的 rails 根目录。这对我很重要,因为我有很多 Rails 引擎。

这也适用于 Rails 4。

于 2011-11-18T09:40:06.977 回答
73

我也在为此苦苦挣扎。这是我最终使用的方法:

<%= 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")) %>
于 2010-08-24T18:06:02.970 回答
54

从视图内部,template_exists?有效,但调用约定不适用于单个部分名称字符串,而是使用 template_exists?(name, prefix, partial)

检查部分路径:app/views/posts/_form.html.slim

采用:

lookup_context.template_exists?("form", "posts", true)
于 2011-08-26T20:21:38.747 回答
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

于 2013-06-08T13:29:20.677 回答
8

我知道这已经得到了回答并且已经有一百万年的历史了,但这就是我最终为我解决这个问题的方式......

导轨 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中尝试过)

于 2015-08-05T18:56:57.300 回答
7

我在很多场合都使用过这个范例并取得了巨大的成功:

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

于 2016-02-16T05:59:59.977 回答
7

你自己的助手呢:

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
于 2016-07-07T13:52:37.913 回答
1

这在 Rails 6.1 中对我有用:

<% if lookup_context.exists?("override_partial", ['path/after/app/views'], true) %>
  <%= render partial: "path/after/app/views/override_partial" %>
<% else %>
  <%= render partial: "default_partial" %>
<% end %>

在这里,我的部分嵌套了一些比正常 ( app/views/path/after/app/views/_override_partial) 更深的级别,这就是为什么我将它添加为前缀数组,但lookup_context.prefixes如果你不需要它,你可以使用它。

我也可以prepend_view_path在控制器上使用。由你决定 :)

于 2021-09-21T22:08:42.250 回答