【发布时间】:2014-01-17 09:54:49
【问题描述】:
通过浏览器的请求只需要它的 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?”
【问题讨论】:
-
您能更清楚地了解您要做什么吗?看看apidock.com/rails/ActionController/Integration/Session/…,它使用了更有用的参数名称。
-
我推测这与路由有关 - HTTP 请求被定向到特定的
controller/action路由;xml请求也是如此。但由于 XML 请求具有不同的标头,因此必须以不同的方式处理。我会进一步研究这个!
标签: ruby-on-rails rspec xmlhttprequest