【问题标题】:Why xml_http_request requires an action as its parameter?为什么 xml_http_request 需要一个动作作为它的参数?
【发布时间】: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


【解决方案1】:

在您的情况下,xhr 需要 :create 因为它似乎是控制器规范。控制器规范是一种单元测试,它们绕过路由器(与集成测试/请求规范不同)。一旦绕过路由器,没有信息应该在测试中调用控制器的哪个动作,因此您必须指定方法和动作。

ActionDispatch::Integration::RequestHelpers 中还定义了 xhr 方法,用于集成测试(请求规范):

xhr(request_method, path, parameters = nil, headers_or_env = nil)

一旦集成测试(和请求规范)是“全栈”测试(并且不绑定到一个控制器),您需要提供 xhr 的方法和路径,控制器/操作将由路由器。

希望它能回答你的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多