2009-09-20 16 views
34

Durante l'apprendimento di Rails, ho creato un'applicazione con un controller Domains nidificata sotto un controller Customers. Sto usando Rails 2.3.4 ed è stata un'esperienza di apprendimento. Sono riuscito a ottenere il percorso seguito istituito:Rails: come modificare i test per una risorsa nidificata?

customer_domains GET /customers/:customer_id/domains(.:format)   {:controller=>"domains", :action=>"index"} 
        POST /customers/:customer_id/domains(.:format)   {:controller=>"domains", :action=>"create"} 
new_customer_domain GET /customers/:customer_id/domains/new(.:format)  {:controller=>"domains", :action=>"new"} 
edit_customer_domain GET /customers/:customer_id/domains/:id/edit(.:format) {:controller=>"domains", :action=>"edit"} 
    customer_domain GET /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"show"} 
        PUT /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"update"} 
        DELETE /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"destroy"} 
      customers GET /customers(.:format)        {:controller=>"customers", :action=>"index"} 
        POST /customers(.:format)        {:controller=>"customers", :action=>"create"} 
     new_customer GET /customers/new(.:format)       {:controller=>"customers", :action=>"new"} 
     edit_customer GET /customers/:id/edit(.:format)      {:controller=>"customers", :action=>"edit"} 
      customer GET /customers/:id(.:format)       {:controller=>"customers", :action=>"show"} 
        PUT /customers/:id(.:format)       {:controller=>"customers", :action=>"update"} 
        DELETE /customers/:id(.:format)       {:controller=>"customers", :action=>"destroy"} 
       root  /            {:controller=>"customers", :action=>"index"} 

Tuttavia, tutti i test per il controller domini non riescono a causa di errori di routing.

Ad esempio, il seguente test (generato dal generatore di risorse di Rails) non riesce, come tutti gli altri test nella classe DomainsControllerTest.

class DomainsControllerTest < ActionController::TestCase 
    test "should get index" do 
    get :index 
    assert_response :success 
    assert_not_nil assigns(:domains) 
    end 
end 

Esso termina con l'errore:

No route matches {:action => "index", :controller => "domains"} 

Questo ha senso poiché i percorsi di default non esistono più e il controllore Domini richiede una @customer da impostare. Ho passato un pomeriggio a cercare il cambiamento necessario, ma quasi tutti i siti parlano dei test Rspec invece dei normali test Rails.

Come si modifica lo domains_controller_test.rb in modo che comprenda la risorsa nidificata?

risposta

47

Passare il customer_id con le richieste farebbe. Qualcosa di simile a questo: -

 
class DomainsControllerTest < ActionController::TestCase 
    test "should get index" do 
    get :index ,:customer_id=> 1 
    assert_response :success 
    assert_not_nil assigns(:domains) 
    end 
end 
+0

Sembra funzionare, Rishav. C'è un modo per ASCIUGARE questo, invece di passare l'id per ogni test separato? –

+1

Martijn, questo è quello che devi fare. Il tuo percorso deve sapere che il cliente lavora. Suppongo che potresti scrivere un helper di test per sostituire la chiamata "get" che riempie automaticamente la parte customer_id dell'hash, ma sembra una cattiva idea a meno che tu non stia scrivendo molti, molti test contro DomainsController. –

+1

Voglio solo precisare perché ASCIUGARSI potrebbe essere una cattiva idea b/c potrebbe essere difficile da leggere e fare il debug. Il codice DRY è ottimo, ma non quando sacrifica la leggibilità. In una prova, vuoi assolutamente essere in grado di vedere cosa sta succedendo. Se riesci a ASCIUGARCI senza sacrificare la leggibilità o aggiungendo fragilità al test, fallo. – WattsInABox

1

Secondo ai tuoi percorsi, domini non esistono più al di fuori del contesto di un cliente. La richiesta ha bisogno di un customer_id per le rotte indicate da abbinare.

Il modo per farlo nel vostro test è:

test "should get index" do 
    get :index, :customer_id=>joe 
end 
+4

Per farlo funziona, ma per il post non sembra funzionare. –

+0

sì, come si risolve questo problema per posta? –

+0

+1 per come puoi farlo con un post – Bastes

1

V'è un gioiello chiamato nester che risolve questo problema esatto. Genera metodi che ti restituiscono un domains_path e simili come se le tue rotte non fossero nidificate. Quando le viste e i test fanno riferimento, ad esempio, a domain_path(domain), i percorsi vengono espansi a customer_domain_path(domain.customer, domain). C'è anche un aiutante ActionController::TestCase che aggiunge :customer_id => @domain.customer per metodi come get, post, ecc

Il valore di default generato test funzionali e viste lavorano fuori dalla scatola con questo approccio. (Disclaimer: l'ho scritto).

Problemi correlati