I'm AJAXifying an existing Rails 3.2 application, and some of the requests that are made from the client are better done asynchronously. To facilitate this, and to cut down on rendering time, I'm giving feedback to the user via alerts. I have a blank div in my application.html.erb file that I add alerts to as needed from certain controller actions like so:
def my_async_controller_action
@user = User.find(params[:id])
begin
#@user.import
flash[:notice] = "Your data is being downloaded."
rescue Exception => bang
flash[:alert] = "There was an error downloading your data: #{bang.message}"
end
respond_to do |format|
format.js { render 'common/flashes' }
end
end
And my common/flashes
file just uses jQuery to append
the alerts to the blank div. While it works fine, I have never seen alerts delivered like this, only via redirects. Is there any unwritten (or written) Rails convention or rule that I'm breaking by taking this approach? Also, is there a way to instead do this as a respond_with? I can't see how I do two different types of rendering from a single line.
If the js
file you are rendering has the same name as the action of your controller, you don't need a respond_to
block.
However, since you are placing your js
file in a common folder, to reuse among your controllers, you have to explicitly tell Rails to render that file. This is totally fine.
If your action only responds to js
, you can use brackets instead of a do ... end
block to make it a one liner:
respond_to { |format| format.js }
However, since you have to specify the name of the js
file, this can get quite ugly, so you can omit the respond_to
block and just do the following:
render 'common/flashes'
This, however, has the inconvenient that if your controller receives an html
request, it will search for a file named flashes.html
inside the common folder. This will most likely return a Template is missing
error. If you want to fix that, you have to add some constraints to the format.
However, if your action also responds to html
, then you should declare the block like this:
respond_to do |format|
format.html
format.js { render 'common/flashes' }
end
You don't need the format.html
, but when you look at the code, you can immediately tell that it responds to both html
and js
requests.
Using a respond_with
block to render different files isn't applicable in your case, since you are only rendering some javascript. respond_with
is used to return some resource in various formats (html, json, xml). This article goes into a little more detail.