了解 Rails 3 的 response_with [英] Understanding Rails 3's respond_with

查看:32
本文介绍了了解 Rails 3 的 response_with的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

利用 ActionController 的新 respond_with 方法...当动作(保存)成功时,它如何确定渲染什么?

Utilizing ActionController's new respond_with method...how does it determine what to render when action (save) is successful and when it's not?

我之所以这么问是因为我试图让一个脚手架生成的规范(包括在下面)通过,如果只是为了我能理解它.该应用程序运行良好,但奇怪的是,当验证失败时,它似乎正在呈现 /carriers(至少浏览器的 URL 是这样说的).然而,规范期望 "new"(就此而言,我也是如此),而是接收 <"">.如果我将规范更改为期望 "" 它仍然失败.

I ask because I'm trying to get a scaffold generated spec (included below) to pass, if only so that I can understand it. The app is working fine but, oddly, it appears to be rendering /carriers (at least that's what the browser's URL says) when a validation fails. Yet, the spec is expecting "new" (and so am I, for that matter) but instead is receiving <"">. If I change the spec to expect "" it still fails.

当它呈现 /carriers 时,该页面会在验证失败的字段旁边显示 error_messages,正如人们所期望的那样.

When it renders /carriers that page shows the error_messages next to the fields that failed validation as one would expect.

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

Can anyone familiar with respond_with see what's happening here?

#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 <"new"> 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 <top (required)>'

推荐答案

tl:dr

向模拟添加错误哈希:

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

这将在 respond_with 中触发所需的行为.

This will trigger the desired behavior in respond_with.

这里发生了什么

post :create

response.code.should == "200"

它失败了 expected: "200", got: "302".因此,它正在重定向而不是在不应该呈现新模板时呈现.它要去哪里?给它一条我们知道会失败的路径:

It fails with expected: "200", got: "302". So it is redirecting instead of rendering the new template when it shouldn't. Where is it going? Give it a path we know will fail:

response.should redirect_to("/")

现在它失败了,预期响应是重定向到 ;但是是重定向到

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

The spec is supposed to pass by rendering the new template, which is the normal course of events after the save on the mock Carrier object returns false. Instead respond_with ends up redirecting to show_carrier_path. Which is just plain wrong. But why?

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

After some digging in the source code, it seems that the controller tries to render 'carriers/create'. There is no such template, so an exception is raised. The rescue block determines the request is a POST and there is nothing in the error hash, upon which the controller redirects to the default resource, which is the mock Carrier.

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

That is puzzling, since the controller should not assume there is a valid model instance. This is a create after all. At this point I can only surmise that the test environment is somehow taking shortcuts.

所以解决方法是提供一个假的错误哈希.通常情况下,save 失败后,哈希中会有一些东西,所以这有点道理.

So the workaround is to provide a fake error hash. Normally something would be in the hash after save fails, so that kinda makes sense.

这篇关于了解 Rails 3 的 response_with的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆