render right

render right

One extension to Rails ActionController::Base#render method I don’t like is the new :update parameter. This is used to render inline RJS in an action like:


class CommentsController < ApplicationController

  def create
    @comment = Comment.new params[:comment]
    respond_to do |wants|
      if @comment.save
        wants.js do
          render :update do |page|
            page.insert_html :bottom, 'comments', render(:partial => 'comment',
                                                         :object => @comment)
            page[:errors].replace_html ''
            page[:comment_form].reset
          end
        end
      else
        wants.js do
          render :update do |page|
            page[:errors].replace_html @comment.errors.full_messages
          end
        end
      end
    end
  end

end

That’s a very simple AJAX comment submission. Instead of creating RJS templates in app/views/comments I just rendered the RJS inline in the action. I think this is bad because

  1. look at how much longer the action is
  2. the nesting makes it a pain to read
  3. in this case the error display will be ugly because I can’t call view methods such as #errormessagesfor in a controller so I’m forced to call ActiveRecord::Errors#full_messages.

I think it’s much better to use RJS views instead. Then the above action becomes:


class CommentsController < ApplicationController

  def create
    @comment = Comment.new params[:comment]
    respond_to do |wants|
      if @comment.save
        wants.js
      else
        wants.js { render :action => 'new.rjs' }
      end
    end
  end

end

create.rjs


  page.inserthtml :bottom, 'comments', render(:partial => 'comment',
                                               :object => @comment)
  page[:errors].replacehtml ''
  page[:comment_form].reset

new.rjs


  page[:errors].replacehtml errormessages_for(:comment)

Then you say but it’s only a couple lines of RJS, why create 2 more files just for that?. My answer would be: do you ever write normal non-AJAX actions like this:


class PostsController < ApplicationController

  def show
    @post = Post.find params[:id]
    html =<<-EOS
      

#{@post.title}

#{@post.body}

EOS render :text => html, :layout => 'application' end end

Of course not.

In my opinion, the :text and :update parameter options in ActionController#Base should both be deprecated.

Jared Carroll Developer