View的测试表明嵌套资源的“无路由匹配”

时间:2012-07-27 17:13:06

标签: ruby-on-rails-3 rspec nested-routes

我的Training模型嵌套在devise User模型下。

/config/routes.rb

devise_for :users, path: 'u'

resources :users, only: ['index','show'], shallow: true do
  resources :trainings
end

>耙路线

        new_user_session GET    /u/sign_in(.:format)                    {:action=>"new", :controller=>"devise/sessions"}
            user_session POST   /u/sign_in(.:format)                    {:action=>"create", :controller=>"devise/sessions"}
    destroy_user_session DELETE /u/sign_out(.:format)                   {:action=>"destroy", :controller=>"devise/sessions"}
           user_password POST   /u/password(.:format)                   {:action=>"create", :controller=>"devise/passwords"}
       new_user_password GET    /u/password/new(.:format)               {:action=>"new", :controller=>"devise/passwords"}
      edit_user_password GET    /u/password/edit(.:format)              {:action=>"edit", :controller=>"devise/passwords"}
                         PUT    /u/password(.:format)                   {:action=>"update", :controller=>"devise/passwords"}
cancel_user_registration GET    /u/cancel(.:format)                     {:action=>"cancel", :controller=>"devise/registrations"}
       user_registration POST   /u(.:format)                            {:action=>"create", :controller=>"devise/registrations"}
   new_user_registration GET    /u/sign_up(.:format)                    {:action=>"new", :controller=>"devise/registrations"}
  edit_user_registration GET    /u/edit(.:format)                       {:action=>"edit", :controller=>"devise/registrations"}
                         PUT    /u(.:format)                            {:action=>"update", :controller=>"devise/registrations"}
                         DELETE /u(.:format)                            {:action=>"destroy", :controller=>"devise/registrations"}
          user_trainings GET    /users/:user_id/trainings(.:format)     {:action=>"index", :controller=>"trainings"}
                         POST   /users/:user_id/trainings(.:format)     {:action=>"create", :controller=>"trainings"}
       new_user_training GET    /users/:user_id/trainings/new(.:format) {:action=>"new", :controller=>"trainings"}
           edit_training GET    /trainings/:id/edit(.:format)           {:action=>"edit", :controller=>"trainings"}
                training GET    /trainings/:id(.:format)                {:action=>"show", :controller=>"trainings"}
                         PUT    /trainings/:id(.:format)                {:action=>"update", :controller=>"trainings"}
                         DELETE /trainings/:id(.:format)                {:action=>"destroy", :controller=>"trainings"}
                   users GET    /users(.:format)                        {:action=>"index", :controller=>"users"}
                    user GET    /users/:id(.:format)                    {:action=>"show", :controller=>"users"}
                    root        /                                       {:controller=>"team", :action=>"index"}
                   teams GET    /teams(.:format)                        {:action=>"index", :controller=>"teams"}
                         POST   /teams(.:format)                        {:action=>"create", :controller=>"teams"}
                new_team GET    /teams/new(.:format)                    {:action=>"new", :controller=>"teams"}
               edit_team GET    /teams/:id/edit(.:format)               {:action=>"edit", :controller=>"teams"}
                    team GET    /teams/:id(.:format)                    {:action=>"show", :controller=>"teams"}
                         PUT    /teams/:id(.:format)                    {:action=>"update", :controller=>"teams"}
                         DELETE /teams/:id(.:format)                    {:action=>"destroy", :controller=>"teams"}

测试视图时我有以下输出:

Failures:

1) trainings/edit renders the edit training form
   Failure/Error: render
   ActionView::Template::Error:
     No route matches {:controller=>"trainings"}
   # ./app/views/trainings/edit.html.erb:6:in `_app_views_trainings_edit_html_erb___268980906337666865_45435220'
   # ./spec/views/trainings/edit.html.erb_spec.rb:12:in `block (2 levels) in <top (required)>'

2) trainings/index renders a list of trainings
   Failure/Error: render
   ActionView::Template::Error:
     No route matches {:action=>"new", :controller=>"trainings"}
   # ./app/views/trainings/index.html.erb:25:in `_app_views_trainings_index_html_erb___2979006340799666900_47907140'
   # ./spec/views/trainings/index.html.erb_spec.rb:18:in `block (2 levels) in <top (required)>'

3) trainings/show renders attributes in <p>
   Failure/Error: render
   ActionView::Template::Error:
     No route matches {:controller=>"trainings"}
   # ./app/views/trainings/show.html.erb:10:in `_app_views_trainings_show_html_erb__2049701071134787176_46584480'
   # ./spec/views/trainings/show.html.erb_spec.rb:12:in `block (2 levels) in <top (required)>'

4) trainings/new renders new training form
   Failure/Error: render
   ActionView::Template::Error:
     undefined method `trainings_path' for #<#<Class:0x00000004a54688>:0x0000000686bec8>
   # ./app/views/trainings/_form.html.erb:1:in `_app_views_trainings__form_html_erb__4221989810981841567_45123700'
   # ./app/views/trainings/new.html.erb:3:in `_app_views_trainings_new_html_erb__472203814357098165_54200400'
   # ./spec/views/trainings/new.html.erb_spec.rb:12:in `block (2 levels) in <top (required)>'

我不会发布所有测试和所有布局文件,因为它会变得太大。相反,我会为一个视图发布测试和布局文件,并尝试将更正扩展到其他视图。

training#index的测试是

/spec/views/trainings/index.html.erb_spec.rb

require 'spec_helper'

describe "trainings/index" do
  before(:each) do
    assign(:trainings, [
      stub_model(Training,
        :user_id => 1,
        :training => "MyText"
      ),
      stub_model(Training,
        :user_id => 1,
        :training => "MyText"
      )
    ])
  end

  it "renders a list of trainings" do
    render
    # Run the generator again with the --webrat flag if you want to use webrat matchers
    assert_select "tr>td", :text => 1.to_s, :count => 2
    assert_select "tr>td", :text => "MyText".to_s, :count => 2
  end
end

/app/views/index.html.rb

<h1>Listing trainings</h1>

<table>
  <tr>
    <th>User</th>
    <th>Training</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @trainings.each do |training| %>
  <tr>
    <td><%= training.user_id %></td>
    <td><%= training.training %></td>
    <td><%= link_to 'Show', training %></td>
    <td><%= link_to 'Edit', edit_training_path(training) %></td>
    <td><%= link_to 'Destroy', training, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Training', new_user_training_path(@user) %>

它表明路线不匹配,但它们在那里。它为什么会发生?!

1 个答案:

答案 0 :(得分:1)

您的索引视图有new_user_training_path(@user),但您的索引规范未创建@user。就像您创建@trainings一样,您还需要在视图规范中创建@user,例如:

  before(:each) do
    assign(:user, 
      stub_model(User,
        :id => 1
      )
    )
    # ...
  end

此外,通过将新视图从ActionView::Template::Error: undefined method 'trainings_path' for #<#<Class:...>>更改为form_for @training(嵌套)来修复form_for [@user, @training]错误。