2010-12-15 11 views
12

Mit ActionControllers neuer Methode respond_with ... wie bestimmt es, was gerendert werden soll, wenn Aktion (Speichern) erfolgreich ist und wenn nicht?Grundlegendes zu Rails 3 response_with

Ich frage, weil ich versuche, eine Scaffold-generierte Spezifikation (unten enthalten) zu erhalten, wenn nur, damit ich es verstehen kann. Die App funktioniert gut, aber seltsamerweise scheint es /carriers zu rendern (zumindest sagt die URL des Browsers), wenn eine Validierung fehlschlägt. Dennoch erwartet die Spezifikation "new" (und ich bin es auch) aber stattdessen erhält <"">. Wenn ich die Spezifikation ändere, um "" zu erwarten, schlägt sie noch fehl.

Wenn es /carriers gerendert wird, zeigt diese Seite die error_messages neben den Feldern, die Validierung fehlgeschlagen, wie man erwarten würde.

Kann jemand mit respond_with vertraut zu sehen, was hier passiert?

#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 das ist versagt:

#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 

mit diesem Fehler:

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

Sie rufen "Carrier.new" sowohl in den '# new'- als auch' # create'-Aktionen Ihres Carrier-Controllers auf. Ich denke, es sollte "Carrier.create (params [: carrier])" in der 'def create' Aktionsmethode sein. – Ernesto

Antwort

23

tl: dr

einen Fehler Hash mit dem Mock hinzufügen:

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

Dies löst das gewünschte Verhalten in respond_with aus.

Was hier los ist,

Fügen Sie diese nach dem post :create

response.code.should == "200" 

Es mit expected: "200", got: "302" ausfällt. Es wird also umgeleitet, anstatt die neue Vorlage zu rendern, wenn dies nicht der Fall ist. Wohin geht es? Geben Sie ihm einen Weg, den wir scheitern wird wissen:

response.should redirect_to("/") 

Jetzt schlägt es mit Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/carriers/1001>

Die Spezifikation durch Rendern der new Vorlage passieren soll, die der normalen Verlauf der Ereignisse nach dem save auf dem Mock ist Trägerobjekt gibt false zurück. Stattdessen wird respond_with auf show_carrier_path weitergeleitet. Was einfach falsch ist. Aber warum?

Nach einigen Ausgrabungen im Quellcode scheint der Controller versucht zu haben, 'carriers/create' zu rendern. Es gibt keine solche Vorlage, daher wird eine Ausnahme ausgelöst. Der Rettungsblock bestimmt, dass die Anfrage ein POST ist und es gibt nichts im Fehlerhash, auf den der Controller zu der Standardressource umleitet, die der Schein Carrier ist.

Das ist verwirrend, da der Controller nicht davon ausgehen sollte, dass es eine gültige Modellinstanz gibt. Dies ist ein create immerhin. An dieser Stelle kann ich nur vermuten, dass die Testumgebung irgendwie Abkürzungen nimmt.

So ist die Problemumgehung, einen falschen Fehler-Hash bereitzustellen. Normalerweise würde etwas im Hash nach save ausfallen, so dass es irgendwie Sinn macht.

+0

Schön gemacht! Würden Sie das als Fehler betrachten? Ich weiß noch nicht genug über Rails, um eine Meinung zu haben. Aber deine Antwort hilft mir beim Lernen! Danke noch einmal... – Meltemi