理解Rails 3的respond_with

利用ActionController的新的respond_with方法……当action(保存)成功时以及何时不成功时,它如何确定要呈现的内容?

我问,因为我试图获得一个脚手架生成的规范(包括在下面),如果只是为了让我能理解它。 该应用程序工作正常,但奇怪的是,当validation失败时,它似乎是渲染/carriers (至少是浏览器的URL所说的)。 然而,规范期待"new" (我也是如此),而是接收 。 如果我将规格改为期望""它仍然失败。

当它呈现/carriers ,该页面会显示错误validation字段旁边的错误消息。

任何熟悉respond_with人都可以看到这里发生了什么吗?

 #carrier.rb validates :name, :presence => true #carriers_controller.rb class CarriersController < ApplicationController respond_to :html, :json ... def new respond_with(@carrier = Carrier.new) end def create @carrier = Carrier.new(params[:carrier]) flash[:success] = 'Carrier was successfully created.' if @carrier.save respond_with(@carrier) end 

规格失败:

 #carriers_controller_spec.rb require 'spec_helper' describe CarriersController do def mock_carrier(stubs={}) (@mock_carrier ||= mock_model(Carrier).as_null_object).tap do |carrier| carrier.stub(stubs) unless stubs.empty? end end describe "POST create" do describe "with invalid params" do it "re-renders the 'new' template" do Carrier.stub(:new) { mock_carrier(:save => false) } post :create, :carrier => {} response.should render_template("new") end end end end 

有这个错误:

  1) CarriersController POST create with invalid params re-renders the 'new' template Failure/Error: response.should render_template("new") expecting  but rendering with . Expected block to return true value. # (eval):2:in `assert_block' # ./spec/controllers/carriers_controller_spec.rb:81:in `block (4 levels) in ' 

TL:博士

向模拟添加错误哈希:

 Carrier.stub(:new) { mock_carrier(:save => false, :errors => { :anything => "any value (even nil)" })} 

这将在respond_with触发所需的行为。

这里发生了什么

post :create之后添加这个

 response.code.should == "200" 

它失败了expected: "200", got: "302" 。 所以它重定向而不是渲染新模板。 它在哪里? 给它一条我们知道会失败的路径:

 response.should redirect_to("/") 

现在它失败, Expected response to be a redirect to but was a redirect to

规范应该通过渲染new模板来传递,这是在模拟Carrier对象上的save返回false之后的正常事件过程。 而是respond_with最终重定向到show_carrier_path 。 这是完全错误的。 但为什么?

在对源代码进行一些挖掘之后,控制器似乎试图渲染“carrier / create”。 没有这样的模板,因此引发了exception。 救援块确定请求是POST并且错误散列中没有任何内容,控制器将重定向到默认资源,即模拟Carrier

这很令人费解,因为控制器不应该假设有一个有效的模型实例。 毕竟这是一个create 。 在这一点上,我只能猜测测试环境是以某种方式走捷径。

所以解决方法是提供假的错误哈希。 通常情况下, save失败后会出现在哈希值中的某些内容,因此有点理解。