Recently I was writing an action in one of my controllers that needed to do a POST to a remote API.
One of the parameters in that POST was a block of HTML.
The first pass was similar to this (ignoring execption handling for the remote call for now):
class UsersController < ApplicationController
def create
@user = User.new params[:user]
if @user.save
markup =<<-EOS
<h2>John Pepper</h2>
Makes amazing [burritos.](http://www.boloco.com)
Is in touch with the blogosphere.
EOS
RemoteApi.update_profile :markup => markup
redirect_to user_path(@user)
else
render :action => :new
end
end
end
I don’t like that HTML in my
controller. Plus that <a>
tag is terrible, I want to use #link_to
but
that’s not available in controllers (and it shouldnt’ be).
Second pass:
class UsersController < ApplicationController
def create
@user = User.new params[:user]
if @user.save
RemoteApi.update_profile
:markup => render(:partial => 'user')
redirect_to user_path(@user)
else
render :action => :new
end
end
end
In user.rhtml
:
<h2>John Pepper</h2>
Makes amazing <%= link_to 'burritos', 'http://www.boloco.com' %>.
Is in touch with the blogosphere.
That’s better. I got the HTML
out of the controller and I can use #link_to instead of an <a>
tag.
But wait: ActionController::DoubleRenderError
. You can’t call render and/or
redirect multiple times in an action (as a side, whoever wrote
ActionController::DoubleRenderError
is awesome - that is the best error
message of any Rails exception).
After looking through the docs i found
ActionController::Base#render_to_string
. This beauty is the same as #render
but does not actually send the result as the response body i.e. it doesn’t count
as a #render call in an action, allowing you to avoid the
ActionController::DoubleRenderError
.
Third pass:
class UsersController < ApplicationController
def create
@user = User.new params[:user]
if @user.save
RemoteApi.update_profile
:markup => render_to_string(:partial => 'user')
redirect_to user_path(@user)
else
render :action => :new
end
end
In user.rhtml
:
<h2>John Pepper</h2>
Makes amazing <%= link_to 'burritos', 'http://www.boloco.com' %>.
Is in touch with the blogosphere.
Sweet. Exactly what I wanted.
Someone else here at t-bot recommended using this strategy for flash messages.
Since flash messages are just text, whenever they get more complicated than 1
sentence it might be good to put them in a partial to keep all that view code
out of your controller, #render_to_string
would allow you to do that.