天天看点

12.2 a working follow button with Ajax

1. in the last chapter, in the user profile screen, the user can click on the follow button, then 

he is redirect back to the original profile screen.

so we can ask, why do we leave that profile page at all?

that is a waste of resource.

right, this is exactly the problem solved by Ajax.

Ajax allows send request to the server without leaving the page.

2. because using Ajax in the form is so common, (for example, when submit the form, you want to use Ajax feature.) rails make it very easy!

you just need to add a param to the form_for

:remote => true

the rails wil automatically use Ajax!

3. (Ajax only works if javascript is enabled in the browser, but it is very easy to degrade gracefully. by this way:

in the server side, we detect it is Ajax or normal request, then deal it differently:

respond_to do |format|

      format.html { redirect_to @user }

      format.js

    end

)

4. we already updated the form code to send an Ajax request, then we need to update the code in the controller to deal with Ajax request, first, TDD.

describe RelationshipsController do
  .
  .
  .
  describe "POST 'create'" do
    .
    .
    .
    it "should create a relationship using Ajax" do
      lambda do
        xhr :post, :create, :relationship => { :followed_id => @followed }
        response.should be_success
      end.should change(Relationship, :count).by(1)
    end
  end

  describe "DELETE 'destroy'" do
    .
    .
    .
    it "should destroy a relationship using Ajax" do
      lambda do
        xhr :delete, :destroy, :id => @relationship
        response.should be_success
      end.should change(Relationship, :count).by(-1)
    end
  end
end
           

 5. next, we will do the action code:

class RelationshipsController < ApplicationController
  before_filter :authenticate
  
  def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end
end
           

 6. next, we need to add two js.erb file to be rendered after the action:

create.js.erb

and 

destroy.js.erb

$("follow_form").update("<%= escape_javascript(render('users/unfollow')) %>")
$("followers").update('<%= "#{@user.followers.count} followers" %>')
           

 $("follow_form").update("<%= escape_javascript(render('users/follow')) %>")

$("followers").update('<%= "#{@user.followers.count} followers" %>')
           

7. here we used prototype javascript, in rails 3.1, they default to use jquery.

in jquery, if you want to get a element by its id, you need to use:

$('#follow_form').html("<%= escape_javascript(render('users/unfollow')) %>")