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')) %>")