【问题标题】:Rails: Render a View (not a partial) From Within a ViewRails:从视图内渲染视图(不是部分视图)
【发布时间】:2013-04-26 01:26:55
【问题描述】:

我有一个控制器可以同时响应htmljshtml 视图呈现整个页面(包括页眉和页脚),而 js 仅替换 #main。除了页眉和页脚之外,两种格式都呈现相同的内容。我可以用三个文件来实现这个效果:

_show.html.erb
<div>Content!</div>

show.html.erb
<%= render "show" %>

show.js.erb
$("#main").fadeIn("<%= escape_javascript(render 'show') %>");

这可行,但如果我不需要单独的 _show 部分,我会更喜欢。不幸的是,这不起作用:

show.html.erb
<div>Content!</div>

show.js.erb
$("#main").fadeIn("<%= escape_javascript(render 'show') %>");

因为 Rails 将寻找 show 部分,而不是实际视图。

有没有办法让 Rails 查找视图文件,而不是部分文件?

【问题讨论】:

  • 您可以使用:file 选项,例如:file =&gt; 'show'。渲染助手会将render 'yourview' 的字符串参数隐式转换为render :partial =&gt; 'yourview'。但是,您将遇到的问题是 js 操作中的查找上下文将“显示”解析为 js 版本,可能会导致无限循环或类似情况。
  • 谢天谢地,它不会循环播放。至少,现在还没有。现在我收到missing template 错误。看起来它甚至找不到自己。
  • 在另一个视图中渲染一个非局部视图并不完全是 Rails Way™。您当前的解决方案可能更好。如果您对命名感到奇怪,请将其重命名为 _body。在这种情况下,您将看到的常见内容是render(@resource),它变成了部分路径,例如resources/_resource.
  • 感谢您的意见。我觉得这可能是最好的方法,但我想先征求其他开发人员的意见。从长远来看,这种方法可能存在一些维护问题,尤其是当我使用此功能编写更多操作时。不过,至少在短期内,我可以设置一台发电机来完成这项工作。
  • 曾几何时,您可以在控制器中执行类似的操作,以便在 javascript 操作中获取 HTML 视图渲染的内容:lookup_context.update_details(:formats =&gt; [:html]) { @content = render_to_string }。然后在 js 视图中你可以render(@content)。然而那是 Rails 3.0.x,即使在那时也可能不是一个干净的解决方案。

标签: ruby-on-rails view render


【解决方案1】:

在另一个视图中渲染一个非局部视图并不完全是 Rails Way™。您当前的解决方案可能更好,而不是一种不常见的方法。如果您对部分名称与动作相同感到奇怪,请将其重命名为 _body 或其他适当的名称。

但是,如果您的视图可以共享,就像在这种情况下看起来一样,您可以将其设置为布局。

这有助于实现这一点,有点违背最小意外原则,如果不存在js 模板,Rails 将为js 操作呈现html 模板。这意味着您可以同时删除 js 模板和部分模板,只需创建一个名为 fadein.js.erb 的布局即可:

# yourviews/show.html.erb
<div>Content!</div>

# layouts/fadein.js.erb
$("#main").fadeIn("<%= escape_javascript(yield) %>");

# YourController.rb
def show
  # ...
  respond_to do |wants|
    wants.html
    wants.js { render :layout => "fadein" }
  end
end

【讨论】:

  • 谢谢一百万。此解决方案将三个文件(show.html.erbshow.js.erb_show.html.erb)合并为一个 show.html.erb。我可以将它应用于模型和动作,并且仍然只需要一个layouts/fadein.js.erb 文件。太棒了!
  • 这真的很好用!太感谢了。我只是有一个问题,我无法让它适用于“创建”场景,其中表单提交应该将我重定向到我刚刚创建的记录。我在form_for 中添加了remote: true,但即使我已经为JS 完成respond_to 以指向布局JS 文件,它也会搜索创建模板。有小费吗?谢谢。
  • @Kopty 它仍然在 javascript 布局中以 HTML 格式呈现模板。所以它仍然会像往常一样寻找创建模板,除非你告诉它不要。如果你想渲染显示模板,你可以做类似render :show, :layout =&gt; "fadein"
  • 感谢您的提示数字。我试过了,得到错误“':show'不是ActiveModel兼容的对象。它必须实现:to_partial_path。”我还尝试对控制器的显示操作进行硬编码,但这也不起作用。
【解决方案2】:

就像其他人提到的那样,在另一个视图中渲染另一个非部分视图是“不是轨道方式”,如果你仍然坚持这样做,一种方法是:

<%= render :file => '<replace with relative/absolute path>' %>

【讨论】:

    【解决方案3】:

    正如您在 cmets 看到的那样,这不是一个好的做法。 Rails 有 viewpartiallayout 的概念。也就是说,视图是唯一一个你应该只使用一次的视图。所以我的建议是:

    1. 如果您觉得可以在当前视图中呈现多个额外的视图,您很可能正在寻找一种布局
    2. 如果您觉得您的某个视图应该在许多页面中呈现,那么您正在寻找一个部分
    3. 如果此视图应仅在其中呈现一个额外的视图,并且该视图应仅在当前视图中呈现,您可以选择以上任何一项都不选择 strong> - 就是这样,使用单个文件

    【讨论】:

      【解决方案4】:

      您只需将上下文传递给您的 render 方法:

      <%= render :template => "show" -%>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多