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>
11 Comments to Calling Rails Render Partial in a Model or Background Task
Leave a Reply
About Justin
Search
Recent Posts
- A Simple Formula for Evaluating Risk
- Not Having a Plan B Makes Plan A More Successful
- Easy Rails API Authentication Using restful-authentication
- God Init.d Script for CentOS
- Private, Authenticated RSS Feeds in Rails
- A Private Web Beta in Seconds with Prefinery
- Backup Your WordPress Blog to Amazon S3 using Ruby
- How to Set an Expires Header in Apache



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})
I thank you for this!!
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?
Did you ever figure this problem out? I am running into the same error (undefined method `url_for’ for nil:NilClass) when using link_to in my partial.
Thanks
FYI – I am running Rails 2.3.5
thank u.
I wanted to use similar technique to render :update. But it gave me an error:
NoMethodError: You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.with_output_buffer
Not sure if I need to include any modules.
you can use in views part,
“partialfolder/partialname” %>
Regards,
Thiyagarajan Veluchamy
Test Lead
[...] to Compulsivo for much of this [...]
It looks as though if you add:
include ActionView::Helpers::UrlHelper
include ActionController::UrlWriter
The nil / noMethodEroor gets resolved.
I got the same “undefined method `url_for’ for nil:NilClass”.
Ttried to add “include ActionView::Helpers::UrlHelper” and “include ActionController::UrlWriter” as Dave suggested but no luck(undefined method ‘include’), I changed “include” to “require” but rails complains “can’t convert Module into String”.
Besides, I need also to use some functions defined in application_helper.rb in the model, how can I do that?
Thanks.