控制器中的 render_to_string 部分格式错误

Posted

技术标签:

【中文标题】控制器中的 render_to_string 部分格式错误【英文标题】:render_to_string partial format error in controller 【发布时间】:2012-11-22 16:33:03 【问题描述】:

在控制器上运行以下代码时出现以下错误。请注意错误中的:formats=>[:json],即使:formats=>[:html] 被传递到render_to_string

我做错了什么?有任何想法吗? 实际上,下面的代码之前运行良好,不确定是什么更改影响了这个错误。 Rails 版本:3.2.8

顺便说一句,模板已经到位:loc/_search_details.html.erb

额外问题:我在哪里可以找到显示哪些参数可以传递给 render_to_string 以及它是如何工作的 api 文档?

错误: ActionView::MissingTemplate(缺少 :locale=>[:en]、:formats=>[:json]、:handlers=>[:erb、:builder、:coffee] 的部分 loc/search_details)。

  respond_to do |format|
    format.json  
      @detail_str = render_to_string(:partial => 'loc/search_details', :layout => false, :formats=>[:html], :locals => :beer_results => @beer_results)
      @list_str = render_to_string(:partial => 'loc/search_list', :layout => false,:formats=>[:html], :locals => :beer_results => @beer_results)
      render :json => :results => @results_hash, :result_details => @detail_str, :result_list => @list_str 

      
  end

【问题讨论】:

我认为:format 不是传递给render 的有效参数。 我没有使用 :format,它是 :formats 是的。我也不认为这是一个有效的参数。 【参考方案1】:

以防万一其他人对此感到困惑,如果您要渲染到字符串,则只需在 format.json 块的上下文之外进行渲染。在您的示例中:

respond_to do |format|
  @detail_str = render_to_string(:partial => 'loc/search_details', :locals => :beer_results => @beer_results)
  @list_str = render_to_string(:partial => 'loc/search_list', :locals => :beer_results => @beer_results)
  format.json      
      render :json => 
        :results => @results_hash, 
        :result_details => @detail_str, 
        :result_list => @list_str 
      

  
end

这样,你不必指定格式或布局为假。

【讨论】:

【参考方案2】:

以防万一有人遇到同样的问题,这对我有用。

我在使用render_to_string 时收到的错误消息与问题中的完全一样,只是format 不匹配。然而,这并不是问题的真正根源。

问题是我的应用是 i18n-ed 并且在 URL 中给出了区域设置。我的routes.rb 看起来像这样:

Quoties::Application.routes.draw do

  scope "(:locale)", locale: /en|pl/ do
    # all routes go here
  end

end

而我的application_controller.rb 看起来像这样:

class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale

  def default_url_options(options=)
    locale = I18n.locale
    locale = nil if locale == :en
     locale: locale  
  end

  def set_locale
    parsed_locale = params[:locale] || 'en'
    I18n.locale = I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
  end
end

(这是我在互联网某处找到的解决方案的略微调整版本。)

它在大多数地方都运行良好。但是,当我在部分中使用路径帮助器时,结果是“缺少部分”错误的原因,比如

<%= item_path(item) %>

有帮助的解决方法是将上面的行替换为:

<%= item_path(item, locale: params[:locale]) %>

我不知道为什么 default_url_options 在这种情况下不起作用,以及为什么 Rails 会引发如此奇怪的异常。

&lt;% self.formats = [:html, :json] %&gt; 上面建议的解决方案只会使错误消息更清晰,因此至少它更改为在item_path 抛出的“没有路由匹配...”。

【讨论】:

【参考方案3】:

见this question 和this issue。由于您正在发出 JSON 请求,因此您的 render_to_string 期望您的部分是 _search_details.json.erb。您可以提供额外的 JSON 部分、重命名部分或将其添加到部分 &lt;% self.formats = [:json, :html] %&gt;,或者尝试在该问题的已接受答案中的解决方法。

【讨论】:

你错了,render_to_string:formats =&gt; [:html] 参数使得它会首先寻找 _search_details.html.erb。我自己测试过,它至少在 Rails 3.2.9 中有效。 -- 这个确实有效 我需要 :formats => [:html] 传递给 render_to_string 方法,并在部分中 让它正常工作。 【参考方案4】:

如果你尝试怎么办

render_to_string(:partial => 'loc/search_details.html.erb', :layout => false, :locals => :beer_results => @beer_results)

或者

with_format("html")  render_to_string(:partial => 'loc/search_details', :layout => false, :locals => :beer_results => @beer_results) 

并添加方法

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

来源:How do I render a partial of a different format in Rails?

【讨论】:

第一个解决方案给出了弃用警告:弃用警告:不推荐在模板名称中传递模板处理程序。您可以简单地删除处理程序名称或通过 render :handlers => [:erb] 代替。 您尝试传递 :handlers 还是第二种解决方案对您有用? 传递处理程序没有帮助,还有另一个关于 :formats html 的弃用警告,如果我添加格式,我会回到我拥有的代码并且它不起作用。第二个解决方案看起来像一个肮脏的 hack :) 稍后我会尝试一下。 这是一个肮脏的黑客,但另一方面,您尝试做的事情也有点肮脏,因此该解决方案适合需要 ;) "顺便说一句,模板已经到位:loc/search_details.html.erb" 大声笑,我希望你在那里打错了,你知道部分文件名以下划线开头,我希望 :-)因为我在一个空白的 Rails 应用程序中尝试了你的代码,它工作正常,当然命名正确。【参考方案5】:

尝试通过

:format => :html

代替

:formats => [:html]

【讨论】:

:formats 在 4.2.1 中有效,而 :format 则无效。

以上是关于控制器中的 render_to_string 部分格式错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 render_to_string 时创建的真实性令牌不同

无法使用 django 的 render_to_string 对单引号 (') 进行编码

指定格式:使用 render_to_string 忽略“xml”

如何将变量从模型传递给 render_to_string?

Rails render_to_string

模板简单梳理