【问题标题】:How do I render a partial of a different format in Rails?如何在 Rails 中呈现不同格式的一部分?
【发布时间】:2010-09-25 05:52:51
【问题描述】:

我正在尝试生成包含一些 HTML 的 JSON 响应。因此,我有/app/views/foo/bar.json.erb

{
  someKey: 'some value',
  someHTML: "<%= h render(:partial => '/foo/baz') -%>"
}

我希望它渲染/app/views/foo/_baz.html.erb,但它只会渲染/app/views/foo/_baz.json.erb。传递:format =&gt; 'html' 没有帮助。

【问题讨论】:

标签: ruby-on-rails format render partial actionview


【解决方案1】:

从 Rails 3.2.3 开始,调用 render :partial 时(仅适用于 respond_to 块之外)。

render formats: [ :html ]

而不是

render format: 'html'

【讨论】:

  • 我想根据上下文可能会有不同的“最佳”答案,因此很难对这个问题进行有意义的投票,但这满足了我从 RJS 中轻松呈现 HTML 模板的需求之一在希望 :format 选项可以工作之后,同名。谢谢!
  • 这也适用于 Rails 5.0.2。但是,请注意,在某些情况下,您可能还需要指定 :content_type 选项——例如从 format.pdf 块内渲染 HTML 模板只能使用 render "template", formats: [:html], content_type: "text/html" 完成。我需要这个,因为我只允许我的电子邮件列表中的成员直接下载my books 的样本——普通访问者会得到一个注册表单。
【解决方案2】:

怎么了

render :partial => '/foo/baz.html.erb'

?我只是尝试从 Atom 构建器模板中呈现 HTML ERB 部分,它工作正常。不需要弄乱全局变量(是的,我知道它们前面有“@”,但它们就是这样)。

虽然您的with_format &amp;block approach 很酷,但其优点是您只需指定格式,而简单的方法也指定模板引擎(ERB/builder/etc)。

【讨论】:

  • 唯一的缺点是,如果您的部分渲染其他部分,它将失败,除非您进入并更改所有渲染部分调用以在其名称中包含“.html.erb”。
  • 您不必为此工作指定模板引擎。 (至少从轨道 3 开始)。以下工作正常:render(:partial => "baz.html")
  • 如果您对不同的语言环境有不同的部分(例如baz.en.html.erbbaz.fr.html.erb)并且您希望render :partials 逻辑来选择正确的部分(带有后备等),则不起作用。
  • 从 rails 3.2.3 开始,我在使用此解决方案时看到以下警告:DEPRECATION WARNING: Passing a template handler in the template name is deprecated. You can simply remove the handler name or pass render :handlers =&gt; [:erb] instead.
  • 这种方法的一个缺点是本地化将寻找foo.baz.html.[your_string] 而不是foo.baz.[your_string]。 zgchurc 的回答是更好的解决方案。
【解决方案3】:

Rails 4 将允许您传递格式参数。所以你可以这样做

render(:partial => 'form', :formats => [:html])} 

请注意,您可以在 Rails 3 中执行类似的操作,但不会将该格式传递给任何子部分(如果表单调用其他部分)。

您可以通过创建 config/initializers/renderer.rb 在 Rails 3 中拥有 Rails 4 功能:

class ActionView::PartialRenderer
  private
  def setup_with_formats(context, options, block)
    formats = Array(options[:formats])
    @lookup_context.formats = formats | @lookup_context.formats
    setup_without_formats(context, options, block)
  end

  alias_method_chain :setup, :formats
end

http://railsguides.net/2012/08/29/rails3-does-not-render-partial-for-specific-format/

【讨论】:

  • 奇怪,我想知道为什么它在 Rails 3.2.19 应用程序中对我不起作用,想知道我的应用程序有什么不同。无法让 ActionView 渲染 :partial 以尊重 :formats arg,似乎根本没有区别,即使使用此补丁也是如此。
【解决方案4】:

对于 Rails 3,with_format 块有效,但有点不同:

  def with_format(format, &block)
    old_formats = formats
    self.formats = [format]
    block.call
    self.formats = old_formats
    nil
  end

【讨论】:

  • 也适用于 rails 3.2.0 :)
【解决方案5】:

roninek's response 的基础上,我发现最佳解决方案如下:

在 /app/helpers/application.rb 中:

def with_format(format, &block)
  old_format = @template_format
  @template_format = format
  result = block.call
  @template_format = old_format
  return result
end

在 /app/views/foo/bar.json 中:

<% with_format('html') do %>
  <%= h render(:partial => '/foo/baz') %>
<% end %>

另一种解决方案是重新定义 render 以接受 :format 参数。

我无法让 render :file 与当地人一起工作,而且没有一些路径迷茫。

【讨论】:

  • 对我来说太老套了。最好指定整个扩展。
  • 对于 rails 3,请参阅 zgchurch 的回答。
【解决方案6】:

在 Rails 3 中,视图有一个格式数组,这意味着您可以将其设置为查找 [:mobile, :html]。设置将默认寻找 :mobile 模板,但回退到 :html 模板。设置它的效果将级联到内部部分。

我能找到的最好但仍然存在缺陷的设置方法是将此行放在每个完整移动模板(但不是部分模板)的顶部。

<% self.formats = [:mobile, :html] %>

缺陷是您必须将该行添加到多个模板中。如果有人知道从 application_controller.rb 设置一次的方法,我很想知道。不幸的是,将该行添加到您的移动布局中不起作用,因为模板是在布局之前呈现的。

【讨论】:

【解决方案7】:

只是详细说明 zgchurch 写的内容:

  • 考虑例外情况
  • 返回被调用块的结果

认为它可能有用。

def with_format(format, &block)
  old_formats = formats
  begin
    self.formats = [format]
    return block.call
  ensure
    self.formats = old_formats
  end
end

【讨论】:

    【解决方案8】:

    你有两个选择:

    1) 使用render :file

    render :file => "foo/_baz.json.erb"
    

    2) 通过设置@template_format 变量将模板格式更改为html

    <% @template_format = "html" %>
    <%= h render(:partial => '/foo/baz') %>
    

    【讨论】:

    • 为我工作,因为我的部分加载了其他部分,我不必更新链中的其他渲染。
    【解决方案9】:

    我有一个名为“api/item.rabl”的文件,我想从 HTML 视图中渲染它,所以我不得不使用:

    render file: 'api/item', formats: [:json]

    file 因为文件名称中没有下划线,formats 而不是format(以及传递和数组))

    【讨论】:

    • 好答案。 Rails 6.1 已弃用在部分名称中包含 .,因此您可以改为:render partial: 'api/item', formats: [:json]
    【解决方案10】:

    似乎传递formats 选项将在较新的Rails 版本(至少3.2)中正确呈现它:

    {
      someKey: 'some value',
      someHTML: "<%= h render('baz', formats: :html) -%>"
    }
    

    【讨论】:

      【解决方案11】:

      当我试图在另一个 xml.builder 视图文件中呈现 XML 部分时,我遇到了这个线程。 以下是一个很好的方法

      xml.items :type => "array" do
          @items.each do |item|
              xml << render(:partial => 'shared/partial.xml.builder', :locals => { :item => item })
          end
      end
      

      是的...完整的文件名也可以在这里使用...

      【讨论】:

      • 这受到@chrisrbailey 在另一个答案中提到的相同的内部部分问题的影响:如果您使用完整文件名调用的部分本身使用部分(没有为每个文件指定完整文件名),它会失败。
      猜你喜欢
      • 1970-01-01
      • 2017-09-26
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      相关资源
      最近更新 更多