2010-12-15 18 views
12

Utilizando el nuevo método respond_with de ActionController ... ¿cómo determina qué renderizar cuando la acción (guardar) es exitosa y cuando no lo es?Understanding Rails 3's response_with

Lo pido porque estoy tratando de obtener una especificación generada por el andamio (incluida a continuación) para aprobar, solo para poder entenderla. La aplicación funciona bien pero, curiosamente, parece estar representando /carriers (al menos eso es lo que dice la URL del navegador) cuando falla una validación. Sin embargo, la especificación espera "new" (y yo también, para el caso), pero en su lugar está recibiendo <"">. Si cambio la especificación para esperar "", aún falla.

Cuando muestra /carriers esa página muestra los mensajes de error junto a los campos que fallaron la validación como uno esperaría.

¿Alguien que esté familiarizado con respond_with puede ver lo que sucede aquí?

#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 

Spec que está fallando:

#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 

con este error:

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)>' 
+1

Está invocando 'Carrier.new' en las acciones' # new' y '# create' de su controlador de operador. Supongo que debería ser 'Carrier.create (params [: carrier])' en el método de acción 'def create'. – Ernesto

Respuesta

23

tl: dr

Añadir un hash de error a la maqueta:

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

Esto disparará el comportamiento deseado en respond_with.

Lo que está pasando aquí

Añadir esto después de la post :create

response.code.should == "200" 

falla con expected: "200", got: "302". Por lo tanto, está redirigiendo en lugar de representar la nueva plantilla cuando no debería. ¿A dónde va? Darle un camino que sabemos que va a fallar:

response.should redirect_to("/") 

Ahora falla con Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/carriers/1001>

La especificación se supone que debe pasar por el template new, que es el curso normal de los acontecimientos después de la save en el simulacro El objeto portador devuelve falso. En su lugar, respond_with termina redirigiendo a show_carrier_path. Lo cual es simplemente incorrecto. ¿Pero por qué?

Después de cavar en el código fuente, parece que el controlador intenta mostrar 'carriers/create'. No existe dicha plantilla, por lo que se genera una excepción. El bloque de rescate determina que la solicitud es un POST y no hay nada en el hash de error, sobre el cual el controlador redirige al recurso predeterminado, que es el simulacro Carrier.

Eso es desconcertante, ya que el controlador no debe suponer que hay una instancia de modelo válida. Este es un create después de todo. En este punto, solo puedo suponer que el entorno de prueba está de alguna manera tomando atajos.

Por lo tanto, la solución consiste en proporcionar un hash de error falso. Normalmente algo estaría en el hash después de que save falla, por lo que tiene sentido.

+0

¡Bien hecho! ¿Consideras esto un error? Todavía no sé lo suficiente sobre Rails para tener una opinión. ¡Pero tu respuesta me está ayudando a aprender! Gracias de nuevo... – Meltemi