通过浏览器的请求只需要其HTTP方法,Rails会根据定义的路由将其调度到适当的控制器操作。那么,为什么xhr
无法做到呢?
http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html#method-i-xml_http_request
以下代码摘自Hartl's rails tutorial
关系资源的路由定义
SampleApp::Application.routes.draw do
resources :relationships, only: [:create, :destroy]
end
# relationships POST /relationships(.:format) relationships#create
# relationship DELETE /relationships/:id(.:format) relationships#destroy
控制器
class RelationshipsController < ApplicationController
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
end
视图模板中的表单发送POST请求导致创建新关系,并且在创建关系后,此表单将消失,而另一个表单将显示“取消关注”按钮。
<%= form_for(current_user.relationships.build(followed_id: @user.id)) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow" %>
<% end %>
此表单只向/relationships
发送POST请求。由于Rails将其路由到relationships#create
(使用params [:relationship] [:followed_id]),因此无需在此处指定操作。
规范导致通过浏览器发送POST请求。
it "should increment the followed user count" do
expect do
click_button "Follow"
end.to change(user.followed_users, :count).by(1)
end
使用Ajax
形式
<%= form_for(current_user.relationships.build(followed_id: @user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
规范xhr
it "should increment the Relationship count" do
expect do
xhr :post, :create, relationship: { followed_id: other_user.id }
end.to change(Relationship, :count).by(1)
end
所以,我想知道为什么
xhr :post, :create, relationship: { followed_id: other_user.id }
需要:create
?我倾向于认为向/relationship
发送带有相关对象的POST请求就足够了,即使使用xhr
也是如此。
显然,这种混淆来自于我对xhr
如何运作的理解不足,现在的问题必须是“xhr
如何运作?为什么xhr
甚至想要:action
?”
答案 0 :(得分:0)
在您的情况下,xhr
需要:create
,因为它似乎是控制器规范。控制器规格是一种单元测试,它们绕过路由器(与集成测试/请求规范不同)。一旦绕过路由器,就没有信息应该在测试中调用控制器的哪个动作,因此你必须同时指定方法和动作。
xhr
中定义的ActionDispatch::Integration::RequestHelpers
方法也用于集成测试(请求规范):
xhr(request_method, path, parameters = nil, headers_or_env = nil)
只要集成测试(和请求规范)是'全栈'测试(并且没有绑定到一个控制器),您需要提供xhr
的方法和路径,并且控制器/操作将是由路由器确定。
希望它能回答你的问题。