Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: How to modify tests for a nested resource?

While learning Rails I've created an application with a Domains controller nested below a Customers controller. I'm using Rails 2.3.4 and it's been a learning experience. I managed to get the below routing set up:

    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"} 

However, all tests for the Domains controller are failing due to routing errors.

For example the following test (generated by Rails' resource generator) fails, as do all other tests in the DomainsControllerTest class.

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

It fails with the error:

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

This makes sense since the default routes no longer exist and the Domains controller requires a @customer to be set. I've spent an afternoon looking for the needed change, but almost every site talks about Rspec tests instead of regular Rails tests.

How do I modify the domains_controller_test.rb so it will understand the nested resource?

like image 745
Martijn Heemels Avatar asked Sep 20 '09 14:09

Martijn Heemels


2 Answers

Passing the customer_id with the requests would do. Something like this :-

 class DomainsControllerTest < ActionController::TestCase   test "should get index" do     get :index ,:customer_id=> 1     assert_response :success     assert_not_nil assigns(:domains)   end end 
like image 107
Rishav Rastogi Avatar answered Oct 02 '22 18:10

Rishav Rastogi


There is a gem called nester that solves this exact problem. It generates methods that give you back a domains_path and similar as if your routes weren't nested. When your views and tests reference, for example, domain_path(domain), the routes are expanded to customer_domain_path(domain.customer, domain). There is also a ActionController::TestCase helper that adds :customer_id => @domain.customer for methods like get, post, etc.

The default generated functional tests and views work out of the box with this approach. (Disclaimer: I wrote it).

like image 34
adamlamar Avatar answered Oct 02 '22 17:10

adamlamar