在rails chapter 12.2.5的教程中,引入了Ajax,以便在不离开页面的情况下将请求异步发送到服务器"。然后在控制器中使用respond_to
方法,允许启用了javascript的浏览器使用Ajax,或者在Ajax被禁用的情况下使用重定向进行响应。
用于在两个用户之间创建关系的表单是:
<%= 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 %>
关系控制器中的相应操作是:
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
为Rails提供使用Ajax的机会是在remote: true
帮助器方法中添加了form_for
。根据教程,控制器必须使用实例变量@user
而不是局部变量user
,以便在remote: true
的表单中使用。
如果没有Ajax,除了remote: true
代码缺失之外,生成的表单将是相同的,并且在控制器中,代码的respond_to
部分将被redirect_to替换;此外,实例变量@user
可以替换为局部变量user
,因此创建操作将是:
def create
user = User.find(params[:followed_id])
current_user.follow(user)
redirect_to user
end
我想知道:为什么控制器必须使用@user
实例变量而不是局部变量user
才能使用Ajax?我尝试使用局部变量,实际上需要刷新才能看到任何变化。表单中的@user
变量(在@user.id
中使用)在用户控制器的show动作中定义,因为表单本身的部分插入show.html.erb
文件中。因此,据我所知,用户控制器中的@user
与关系控制器中的@user
之间没有任何关联。
答案 0 :(得分:5)
您需要将其声明为实例变量(@),以便在您的视图中可用。是的,使用ajax你没有重新加载页面,但你发回js而不是html。 rails会响应create.js.erb
中的任何内容。请注意,在此文件中,您需要访问@user数据;如果您将其声明为user
而不是@user
,则无法访问它:
#app/views/relationships/create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= @user.followers.count %>');