This post originated from an RSS feed registered with Ruby Buzz
by Obie Fernandez.
Original Post: render :text gotcha
Feed Title: Obie On Rails (Has It Been 9 Years Already?)
Feed URL: http://jroller.com/obie/feed/entries/rss
Feed Description: Obie Fernandez talks about life as a technologist, mostly as ramblings about software development and consulting. Nowadays it's pretty much all about Ruby and Ruby on Rails.
Hi everyone! Hope you're all having a nice holiday season and I wish you a great new year. This morning I diagnosed a production issue that I think qualifies as a gotcha and which probably affects more than a few Rails apps out there. The gotcha has to do with proper use of render :text in controller actions, used to send plain-text as the response back to the browser. It doesn't work with nil!
In ActionController::Base, in a big if/else statement inside the render method, the following conditional is used to determine whether to trigger text rendering:
if text = options[:text]
render_for_text(text, options[:status])
If you're passing render :text the result of a method call (for instance, an object attribute) and it gets a nil, the render handling code in Rails is going to drop right down to the default rendering behavior, which is to try to render what was passed to it as a file:
Of course, if you didn't intend for that to happen, you're probably going to end up with an error, specifically Missing template
[RAILS_ROOT]/vendor/rails/actionpack/lib/action_controller/base.rb:1242:in `assert_existence_of_template_file'.
The most notable use of render :text in the Rails codebase itself is the in_place_edit functionality, which is an official plugin in Rails 2. It handles this gotcha by calling to_s on the result of the method call:
def in_place_edit_for(object, attribute, options = {})
define_method("set_#{object}_#{attribute}") do
@item = object.to_s.camelize.constantize.find(params[:id])
@item.update_attribute(attribute, params[:value])
render :text => @item.send(attribute).to_s
end
end