Calling Rails Render Partial in a Model or Background Task

Why?

You want to store raw HTML in the database for a given model and you want to do this with the ease of partials and not a bunch of nasty string manipulation.

Rails makes this difficult for you by not giving you access to the render method when not called from ActionController.  However, you’d like to call the partial helper from within a model, or a background task (such as BackgrounDRb or Starling).

How?

As an example, let’s say you have a Page model made up of a title and a body.  You’d like to cache what a rendered page would look like in the model as the attribute cached_content.

The old way.  This really sucks.

class Page < ActiveRecord::Base

  def write_cache
    the_content = "<div class='title'>"
    the_content += "<h1>#{self.title}</h1>"
    the_content += "</div>"
    the_content += "<div class='body'>"
    the_content += "#{self.body}"
    the_content += "</div>"

    self.cached_content = the_content
    self.save
  end

end

The new way.  This is so much easier and cleaner.

class Page < ActiveRecord::Base

  def write_cache
    self.cached_content = ActionView::Base.new(Rails::Configuration.new.view_path).render(:partial => "pages/show", :locals => {:page => self})
    self.save
  end

end

app/views/pages/_show.html.erb

<div class="title">
  <h1>
    <%= page.title %>
  </h1>
</div>

<div class="body">
  <%= page.body %>
</div>
Wednesday, October 29th, 2008 Programming

4 Comments to Calling Rails Render Partial in a Model or Background Task

  1. Love the tip, it breaks though when your view code uses helper methods, to do this, I stole from Rails internal private method, initialize_template_class:

    template_instance = ActionView::Base.new(Rails::Configuration.new.view_path)

    template_instance.extend ApplicationController.master_helper_module

    content = template_instance.render(:partial => self.view_path(self.profile) + ‘/show’, :locals => {:item => self})

  2. Joe Goggins on November 10th, 2008
  3. I thank you for this!!

  4. Cobus on November 19th, 2008
  5. I take it link_to/url_for would fit into the situation Joe Goggins mentions above?

    I’m trying to render a partial with some links to nested resources and I keep getting this error:

    The error occurred while evaluating nil.url_for

    I tried out Joe’s sample code as well, still no dice. Anyone have any thoughts?

  6. Joel on November 22nd, 2008
  7. thank u.

  8. holin on November 25th, 2008

Leave a comment

Search

 

About Us

Located in beautifully weird Austin, Texas, Compulsivo has been obsessing over writing simple Web software using Ruby on Rails for nearly two years.

Stay Informed

Our Products

Prefinery: Simple, online beta management software

Simple, online beta management software focused on improving beta testing by making it simple to manage your software online, and easy to collect customer feedback through surveys, comments, and bug reports.


Flashlight: Simple and affordable sales tracking and inventory management

Simple and affordable sales tracking and inventory management for artists, craftspeople, hobbyists, and other small business owners who make and sell stuff.