I have a Training
model that's nested under a devise
User
model.
/config/routes.rb
devise_for :users, path: 'u'
resources :users, only: ['index','show'], shallow: true do
resources :trainings
end
> rake routes
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"}
I'm having the following outputs when testing views:
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)>'
I won't post all tests and all layout files because it would get too big. Instead I'll post test and layout file for one view, and try to extend the correction to the others.
The test for training#index
is
/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) %>
It indicates that routes doens't match, but they are there. Why is it happening?!
Your index view has new_user_training_path(@user)
, but your index spec is not creating @user
. Just like you created @trainings
you also need to create @user
in your view spec, something like:
before(:each) do
assign(:user,
stub_model(User,
:id => 1
)
)
# ...
end
Also, the ActionView::Template::Error: undefined method 'trainings_path' for #<#<Class:...>>
error is fixed by changing your new view from form_for @training
to form_for [@user, @training]
(nested).