10

I get the below error when running the below code on a controller. Please note the :formats=>[:json] in the error, even though :formats=>[:html] is passed into render_to_string

What am I doing wrong? Any ideas? Actually, the code below worked fine before, not sure what changes influenced this error. Rails version: 3.2.8

btw the template is definitely in place: loc/_search_details.html.erb

Bonus question: where can I find the api documentation showing what parameters can be passed to render_to_string and how it works?

Error: ActionView::MissingTemplate (Missing partial loc/search_details with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :coffee]}.

  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
vrepsys
  • 2,143
  • 4
  • 25
  • 37

5 Answers5

4

What if you try

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

Or

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

And add the method

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

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

Community
  • 1
  • 1
mrbrdo
  • 7,968
  • 4
  • 32
  • 36
  • The first solution gives deprecation warning: DEPRECATION WARNING: Passing a template handler in the template name is deprecated. You can simply remove the handler name or pass render :handlers => [:erb] instead. – vrepsys Dec 04 '12 at 23:10
  • Did you try passing :handlers or did the second solution work for you? – mrbrdo Dec 04 '12 at 23:18
  • passing handlers does not help, there's another deprecation warning about :formats html, if I add formats I'm back to the code I have and it doesn't work. The second solution looks like a dirty hack :) I'll try it a bit later. – vrepsys Dec 04 '12 at 23:22
  • It is a dirty hack, but on the other hand what you are trying to do is also kind of dirty, so the solution fits the need ;) – mrbrdo Dec 04 '12 at 23:24
  • "btw the template is definitely in place: loc/search_details.html.erb" lol, I hope you made a typo there, you do know that partial filenames start with an underscore I hope :-) Because I tried your code in a blank rails app and it works fine, with correctly named partial of course. – mrbrdo Dec 04 '12 at 23:52
  • yes, it was a typo :) fixed now. So it just works?? It still doesn't for me.. I'll try and find the problem tomorrow. thx. – vrepsys Dec 05 '12 at 00:03
  • Yes it just works for me, I copied your setup: format.json ... "@detail_str = render_to_string(:partial => 'home/index_details', :layout => false, :formats=>[:html], :locals => {:beer_results => 1}) ; render :json => {:result_details => @detail_str }" And the file app/views/home/_index_details.html.erb. It renders properly for me. If you have problems make a simple rails app to test it and go from there. – mrbrdo Dec 05 '12 at 00:18
4

See this question and this issue. Since you're making a JSON request your render_to_string is expecting your partial to be _search_details.json.erb. You can either provide an additional JSON partial, rename the partial or add this to the partial <% self.formats = [:json, :html] %>, or alternatively, try the workaround in the accepted answer to that question.

Community
  • 1
  • 1
David
  • 7,310
  • 6
  • 41
  • 63
  • 3
    You're wrong, the `:formats => [:html]` parameter to `render_to_string` makes it so it will look for `_search_details.html.erb` first. I've tested it myself, and it works, at least in Rails 3.2.9. – mrbrdo Dec 05 '12 at 00:21
  • <% self.formats = [:json, :html] %> -- this one actually works – vrepsys Dec 05 '12 at 11:45
  • I needed both :formats => [:html] passed to render_to_string method, and <% self.formats = [:json, :html] %> in the partial to get it to work correctly. – Mitya Jun 23 '13 at 17:51
2

Just in case someone else stubmles on this, if you're rendering to a string, you just have to do the rendering outside the context of the format.json block. In your example:

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

In this way, you don't have to specify formats or layout is false.

onetwopunch
  • 3,279
  • 2
  • 29
  • 44
1

Try to pass

:format => :html

Instead of

:formats => [:html]
mrbrdo
  • 7,968
  • 4
  • 32
  • 36
1

Just in case someone has the same problem, here's what worked for me.

The error message I had when using render_to_string was exactly the same as in the question, complete with the format mismatch. However, it was not really the source of the problem.

The problem was that my app was i18n-ed and the locale was given in the URL. My routes.rb looks like this:

Quoties::Application.routes.draw do

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

end

and my application_controller.rb looked like this:

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

(It's a slightly tweaked version of a solution I found somewhere on the Internet.)

It worked pretty well in most places. However, it turned out to be the cause of the 'missing partial' error when I was using a path helper in the partial, say

<%= item_path(item) %>

The workaround which helped was replacing the above line with:

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

I've got no idea why default_url_options do not work in this case and why Rails raised such a weird exception.

<% self.formats = [:html, :json] %> solution suggested above only made the error message clearer, so that at least it changed to 'no route matches...' thrown at item_path.

kamilk
  • 3,829
  • 1
  • 27
  • 40