In chapter 12.2.5 of the rails tutorial, Ajax is introduced in order to "send requests asynchronously to the server without leaving the page". The respond_to method is then used in the controller to allow browsers with enabled javascript to use Ajax or to respond with a redirect in case Ajax is disabled.
The form used to create a relationship between two users is:
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, @user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
The corresponding action in the relationships controller is:
def create
@user = User.find(params[:followed_id])
current_user.follow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
What gives Rails the opportunity to use Ajax is the addition of remote: true in the form_for helper method. According to the tutorial, it is necessary for the controller to use the instance variable @user instead of the local variable user for use in the form with remote: true.
Without Ajax, the resulting form would be identical except for the remote: true code absence, and in the controller the respond_to section of code would be replaced by a redirect_to; moreover, the instance variable @user can be replaced by the local variable user, so that the create action would be:
def create
user = User.find(params[:followed_id])
current_user.follow(user)
redirect_to user
end
I am wondering: why it is necessary for the controller to use the @user instance variable instead of the local variable user in order to use Ajax? I tried to use the local variable, and in effect a refresh is required to see any change. The @user variable in the form, which is used in @user.id, is defined in the show action for the users controller, because the partial for the form itself is inserted in the show.html.erb file. So, as far as I understand, there is no connection between @user in the users controller and @user in the relationships controller.
You need to declare it as instance variable (@) so it will be available in your view. Yes, using ajax you are not reloading the page, but you are sending back js instead of html. rails will respond with whatever is in create.js.erb. Notice that in this file you need access to the @user data; if you declare it as user instead of @user, it will not be accessible:
#app/views/relationships/create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= @user.followers.count %>');