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

Dan*_*ier 97 ruby-on-rails partial

当我渲染一个不存在的部分时,我得到一个例外.我想在渲染之前检查是否存在部分,如果它不存在,我将渲染其他内容.我在.erb文件中执行了以下代码,但我认为应该有更好的方法来执行此操作:

    <% begin %>
      <%= render :partial => "#{dynamic_partial}" %>
    <% rescue ActionView::MissingTemplate %>
      Can't show this data!
    <% end %>
Run Code Online (Sandbox Code Playgroud)

小智 97

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

lookup_context.find_all('posts/_form').any?
Run Code Online (Sandbox Code Playgroud)

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

这也适用于Rails 4.

  • lookup_context.exists?('posts/find')也应该有用 (23认同)
  • lookup_context.exists?('posts/find')对我不起作用.相反,我在本例中使用了lookup_context.exists?(name,prefix,partial)或lookup_content.exists?('find','posts',true). (9认同)
  • 这是检查模板的当前(rails> = 3.2)方法(source [apidock](http://apidock.com/rails/ActionView/LookupContext/ViewPaths/template_exists%3F)) (2认同)
  • 这比接受的答案要清晰得多. (2认同)
  • 如果部分与当前视图模板位于同一文件夹中,则可以使用`lookup_context.exists?("find",lookup_context.prefixes, true)`。这样,您不需要将视图目录硬编码到调用中。请注意,这是针对部分的。对于非部分,省略最后一个参数(或使用 false 而不是 true) (2认同)

Jef*_*eff 69

我也在努力解决这个问题.这是我最终使用的方法:

<%= render :partial => "#{dynamic_partial}" rescue nil %>
Run Code Online (Sandbox Code Playgroud)

基本上,如果部分不存在,则什么也不做.但是,如果缺少部分内容,您是否想要打印一些内容?

编辑1:哦,我在阅读理解上失败了.你确实说过想要渲染别的东西.在那种情况下,这个怎么样?

<%= render :partial => "#{dynamic_partial}" rescue render :partial => 'partial_that_actually_exists' %>
Run Code Online (Sandbox Code Playgroud)

要么

<%= render :partial => "#{dynamic_partial}" rescue "Can't show this data!" %>
Run Code Online (Sandbox Code Playgroud)

编辑2:

备选方案:检查是否存在部分文件:

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

  • 我真的不喜欢这个解决方案.救援是昂贵的,File.exists?假设部分只能在一个位置.使用lookup_context的@ Rein的解决方案是我相信的方法. (8认同)
  • 我的问题是我不想使用Exceptions来进行流量控制,这是一种反模式:http://stackoverflow.com/questions/1546514/java-exceptions-as-control-flow (6认同)
  • 例外是一种流控制,用于处理程序正常运行之外发生的事情.如果动态部分应该在那里但是出现了问题并且它最终没有存在,那么这是一个合理的例外用途(IMO,当然 - 正确使用例外是一个神圣的战争本身).我想说你的替代方法是检查文件系统是否存在实际文件.我将用该代码更新我的答案. (6认同)
  • 如果您有不同类型的异常,`rescue nil`和`... rescue ...`方法将隐藏它.这导致了很难调试的错误. (5认同)
  • 我喜欢这个解决方案,然而它吞下了局部抛出的任何异常.恕我直言,这使得追踪错误更加困难. (3认同)

Luk*_*off 52

从视图中,template_exists?有效,但调用约定不适用于单个部分名称字符串,而是需要template_exists?(名称,前缀,部分)

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

使用:

lookup_context.template_exists?("form", "posts", true)
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用lookup_context.prefixes作为第二个参数:lookup_context.template_exists?("form",lookup_context.prefixes,true) (2认同)

Fla*_*kou 30

在Rails 3.2.13中,如果你在控制器中,你可以使用:

template_exists?("#{dynamic_partial}", _prefixes, true)
Run Code Online (Sandbox Code Playgroud)

template_exists?lookupcontext如你所见,被委派给AbstractController::ViewPaths

_prefixes 给出了控制器继承链的上下文.

true 因为你正在寻找一个部分(如果你想要一个普通的模板,你可以省略这个参数).

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

  • 从视图(例如布局),这可以工作:`lookup_context.template_exists?("navbar",controller._prefixes,:partial)`.这告诉我呈现此布局的当前模板是否具有所声明的"navbar"部分,如果是,我可以渲染它.我传递`:partial`只是为了明确布尔是什么 - `:partial`是真的.感谢`_prefixes`位,@ Flackou! (4认同)

afx*_*jzs 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
Run Code Online (Sandbox Code Playgroud)

现在而不是打电话

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

我打电话 <%= render_if_exists "#{dynamic_path}" %>

希望有所帮助.(还没试过rails3)


br3*_*3nt 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
%>
Run Code Online (Sandbox Code Playgroud)

上述代码的好处是我们可以处理两个特定情况:

  • 部分确实缺失了
  • 部分存在,但由于某种原因它抛出了一个错误

如果我们只是使用代码<%= render :partial => "#{dynamic_partial}" rescue nil %>或某些衍生物,那么部分可能存在,但会引发一个异常,这个异常会被静默吃掉并成为调试的痛苦根源.


And*_*rey 5

你自己的帮手呢:

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
Run Code Online (Sandbox Code Playgroud)