missing rails api: render_with_format

So in newish versions of Rails, if you say:

render(:partial => “foo”)

And you are current rendering format “html”, then rails will look for a template called “_foo.html.[erb|builder]”, and failing that look for “foo.[erb|builder”.  If your in some other format, than it’ll look for that in place of ‘html’.

So what if you are rendering an ‘atom’ format feed (or really any other XML format), and your going to put some html in the atom:summary (for example), and you want to render a partial to do it?  render(:partial => “foo”) is not going to find _foo.html.erb, because it’s going to look for _foo.xml.erb, and then _foo.erb, and then throw an exception when it finds nothing.

So one solution is to be explicit in your render call: render(:partial => “foo.html.erb” ).

That works. But what if _foo.html.erb itself calls OTHER partials, and just uses the shortcut name to call them? Now THOSE calls will raise exceptions.

So you could use the full .html.erb version every single time you use a render anywhere, just in case (never can predict what you someday might want to call from XML). But that’s kind of ugly, and what if you’re writing framework/plugin/library code (like for Blacklight atom generation) you want to be easily callable by everyone else without having to put weird restrictions like that on them?

It seems that Rails render really needs a :format option to force a certain format for that render call. But it sadly does not have one.

But in a few lines of Rails code using internal Rails API (that, yeah, could break in a future version), you can give it one.  With the info on the internal Rails API from James A. Rosen found via google, there are two ways to do it. James more flexible way:

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

Alternate idea of more constrained-to-render-usecase way:

  def render_with_format(hash)
    format = hash.delete(:format)
    original_format = @template_format
    @template_format = format
    begin
      render(hash)
    ensure
      @template_format = original_format
    end
  end
This entry was posted in General. Bookmark the permalink.

3 Responses to missing rails api: render_with_format

  1. Pingback: HotStuff 2.0 » Blog Archive » Word of the Day: “atom”

  2. Mike says:

    Is there anything for the latest version of Rails 3 now? The last code sample doesn’t seem to work.

  3. jrochkind says:

    Mike: Haven’t tried it myself, but this stack overflow suggests a similar technique that works in Rails3:

    http://stackoverflow.com/questions/339130/how-do-i-render-a-partial-of-a-different-format-in-rails/5074120#5074120

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s