RailsではフォームのAjax化を機能として提供してくれるが、あえてそれを使わないパターンを試してみる
ポイントはcsrf対策向けの処理を自分で書かなければならないというところか
user_controller.rb
  # POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end
user.html.erb
<form id="the-form" action="/users.json" method = "POST">
  <input type="text" name="user[name]" value="">
  <button>submit</button>
</form>
http://ginpen.com/2013/05/07/jquery-ajax-form/
を参考にAjaxの処理を追加。
CSRFトークンをページから読み取り追加してあげる。
users.js
jQuery(function($) {
    $('#the-form').submit(function(event) {
        // HTMLでの送信をキャンセル
        event.preventDefault();
        // 操作対象のフォーム要素を取得
        var $form = $(this);
        // 送信ボタンを取得
        // (後で使う: 二重送信を防止する。)
        var $button = $form.find('button');
        $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
            var token;
            if (!options.crossDomain) {
              token = $('meta[name="csrf-token"]').attr('content');
              if (token) {
                   return jqXHR.setRequestHeader('X-CSRF-Token', token);
               }
            }
        });
        // 送信
        $.ajax({
            url: $form.attr('action'),
            type: $form.attr('method'),
            data: $form.serialize(),
            timeout: 10000,  // 単位はミリ秒
            // 送信前
            beforeSend: function(xhr, settings) {
                // ボタンを無効化し、二重送信を防止
                $button.attr('disabled', true);
            },
            // 応答後
            complete: function(xhr, textStatus) {
                // ボタンを有効化し、再送信を許可
                $button.attr('disabled', false);
            },
            // 通信成功時の処理
            success: function(result, textStatus, xhr) {
                // 入力値を初期化
             $('tbody').append(result.name);
            },
            // 通信失敗時の処理
            error: function(xhr, textStatus, error) {}
        });
    });
});