ruby-on-rails-3coding-styleruby-on-rails-3.2convention-over-configur

Is there any issue with using respond_to blocks in controller actions like this?


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.


Solution

    1. 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.

    2. 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.

    3. 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.

    4. 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.