2

Rails 3.1.0 Rspec 2

In a view spec for a nested resource, do I need to instantiate/stub the parent resource before I stub the nested resource?

I am asking this because all my view specs are failing for a new nested resource I have introduced in my application. The nested resource works as expected when I manually test it though :( Here's how my edit view spec looks like.

----- "./spec/views/sub_categories/edit.html.erb_spec.rb" - start -------- 


require 'spec_helper'  describe "sub_categories/edit.html.erb" do    before(:each) do 
    @sub_category = assign(:sub_category, stub_model(SubCategory, 
      :name => 'International interest rates', 
      :description => 'Comprehensive rates covering Australia, NZ,  Malaysia and Singapore', 
      :category_id => 3, 
      :created_by => 1, 
      :updated_by => 1 
    ))    end    it "renders the edit sub category form" do 
    render 
    # Run the generator again with the --webrat flag if you want to  use webrat matchers 
    assert_select "form", :action =>  category_sub_categories(@sub_category), :method => "post" do 
      assert_select "input#sub_category_name", :name =>  "sub_category[name]" 
      assert_select "textarea#sub_category_description", :name =>  "sub_category[description]" 
    end    end  end 
--- "./spec/views/sub_categories/edit.html.erb_spec.rb" - end --------

Here's an extract of the failure:

----------- extract start ------------------------- 

  1) sub_categories/edit.html.erb renders the edit sub category form 
     Failure/Error: render 
     ActionView::Template::Error: 
       undefined method `sub_category_path' for #<#<Class:  0x0000010127d2b8>:0x000001016e2380> 
     # ./app/views/sub_categories/_form.html.erb:1:in  `_app_views_sub_categories__form_html_erb__4092631658606598204_2155519360'

     # ./app/views/sub_categories/edit.html.erb:3:in  `_app_views_sub_categories_edit_html_erb___3853358586184509671_2155544160'

     # ./spec/views/sub_categories/edit.html.erb_spec.rb:15:in `block  (2 levels) in <top (required)>' 
----------- extract end -------------------------

Here's what my form partial looks like

----- app/views/sub_categories/_form.html.erb start --------------------- 

<%= form_for [@category, @sub_category] do |f| %>    <% if @sub_category.errors.any? %> 
    <div id="error_explanation"> 
      <h2><%= pluralize(@sub_category.errors.count, "error") %>  prohibited this sub_category from being saved:</h2> 
      <ul> 
      <% @sub_category.errors.full_messages.each do |msg| %> 
        <li><%= msg %></li> 
      <% end %> 
      </ul> 
    </div>    <% end %>    <div class="field"> 
    <%= f.label :name %><br /> 
    <%= f.text_field :name %>    </div>    <div class="field"> 
    <%= f.label :description %><br /> 
    <%= f.text_area :description %>    </div>    <div class="actions"> 
    <%= f.submit %>    </div>  <% end %> 

----- app/views/sub_categories/_form.html.erb end ---------------------

Here's what I see when I run 'rake routes':

------- routes start ---------------------------     category_sub_categories GET    /categories/:category_id/  sub_categories(.:format)  {:action=>"index", :controller=>"sub_categories"} 
                           POST   /categories/:category_id/  sub_categories(.:format)  {:action=>"create", :controller=>"sub_categories"}   new_category_sub_category GET    /categories/:category_id/  sub_categories/new(.:format)  {:action=>"new", :controller=>"sub_categories"}  edit_category_sub_category GET    /categories/:category_id/  sub_categories/:id/edit(.:format)  {:action=>"edit", :controller=>"sub_categories"} 
     category_sub_category GET    /categories/:category_id/  sub_categories/:id(.:format)  {:action=>"show", :controller=>"sub_categories"} 
                           PUT    /categories/:category_id/  sub_categories/:id(.:format)  {:action=>"update", :controller=>"sub_categories"} 
                           DELETE /categories/:category_id/  sub_categories/:id(.:format)  {:action=>"destroy", :controller=>"sub_categories"} 
                categories GET    /  categories(.:format)  {:action=>"index", :controller=>"categories"} 
                           POST   /  categories(.:format)  {:action=>"create", :controller=>"categories"} 
              new_category GET    /categories/  new(.:format)  {:action=>"new", :controller=>"categories"} 
             edit_category GET    /categories/:id/  edit(.:format)  {:action=>"edit", :controller=>"categories"} 
                  category GET    /  categories/:id(.:format)  {:action=>"show", :controller=>"categories"} 
                           PUT    /  categories/:id(.:format)  {:action=>"update", :controller=>"categories"} 
                           DELETE /  categories/:id(.:format)  {:action=>"destroy", :controller=>"categories"} 
                      root        / 
------- routes end ---------------------------

The form partial has been properly fitted with the parent resource and the nested resource (ie. "form_for [@category, @sub_category]" ). It seems that it's calling a route, sub_category_path which I have never specified.

The error comes up when an edit/create form is to be created where a form partial is called.

I am really puzzled on why this is happening and have consulted the search results I had via google for 'nested resources with rspec' , 'Rails in Action 3' by Yehuda Katz, and the Rspec book :(

If anyone knows what I am missing, I would love to hear your thoughts.

Michiel van Oosterhout
  • 22,839
  • 15
  • 90
  • 132
Gordon
  • 61
  • 1
  • 4

1 Answers1

1

Your category_id is in @sub_category.category_id not in @category which you use in the view (which is nil now).

[@category, @sub_category] is just a shortcut for url_for([@category, @sub_category]) which returns single resource path if one the arguments is nil.

Check the guide.

jibiel
  • 8,175
  • 7
  • 51
  • 74
  • thanks for that, jibiel. You're right! I changed the object to be given to the category_sub_categories() path with a stubbed @category object and that error disappears. – Gordon Jan 29 '12 at 08:44
  • Unfortunately, another error has surfaced. Failure/Error: render ActionView::Template::Error: No route matches {:controller=>"sub_categories"} # ./app/views/sub_categories/edit.html.erb:6:in `_app_views_sub_categories_edit_html_erb___1129420093949643160_2199243480' # ./spec/views/sub_categories/edit.html.erb_spec.rb:21:in `block (2 levels) in ' I know my controller is defined as "SubCategoriesController" in app/controllers/sub_categories_controller.rb. I got to look into this. Perhaps the routes file. Will report later :) thank you :) – Gordon Jan 29 '12 at 08:46
  • in your `./spec/views/sub_categories/edit.html.erb_spec.rb`. The short answer is **yes**, you have to stub parent resource in this case. – jibiel Jan 29 '12 at 08:55
  • hello, jibiel, i have looked at my routes file and things seem to be in good order. ` resources :categories do resources :sub_categories end` – Gordon Jan 31 '12 at 07:04
  • `ActionView::Template::Error: No route matches {:controller=>"sub_categories"}` There's nothing wrong with `controller`. It says you haven't specified `action` so rails can't match any of the defined routes. Drop your `edit.html.erb_spec.rb`, `edit.html.erb` and `routes.rb` into http://pastebin.com/ so i could take a look. – jibiel Jan 31 '12 at 08:11
  • hang on, i had a look at it again and yes, i figured it out. It was caused by another link within edit.html.erb, which was missing a resource object. Fixed that and I am now facing another issue. I think I can give it a go. Thank you very much for your help, @jibiel! :) – Gordon Jan 31 '12 at 09:21
  • not sure what happened to my pastebin url which i had put in 2 comments earlier but for reference, here [it is again](http://pastebin.com/ViP68MGL). – Gordon Jan 31 '12 at 09:32
  • I've got this other error now which I can't figure out the error message: 1) sub_categories/edit.html.erb renders the edit sub category form Failure/Error: assert_select "form", :action => category_sub_category_path(@category), :method => "post" do ActionController::RoutingError: No route matches {:action=>"show", :controller=>"sub_categories", :category_id=>#}. http://pastebin.com/b8iCYrpL – Gordon Jan 31 '12 at 09:54
  • Don't know why rspec is not recognising the parent factory girl object (which is legitimate because it contains all the attributes of the class of a parent object, Category). Weird – Gordon Jan 31 '12 at 10:10