Reputation: 488
Working through the "Ruby on rails 3 essential training" I'm encountering an issue with my routes and URL's. I have created a sujects_controller with a 'list' action and a 'show' action. Within my localhost, when I enter in: localhost:3000.subjects/list, I get an error, 'couldn't find Subject with id=list' But, when I enter in: localhost:3000.subjects. I get the list that should have come up when entering the first URL. Also, after entering this second URL, I have links for Show, Edit, and Delete. When I hover my mouse over the link "Show", at the bottom of the page, the future output reads localhost.3000/subjects(3). This link works. But, according to my instructors tutorials, it should read, localhost.3000/subjects/show/3. For some reason my links and/or actions, aren't working appropriately and I'm not sure why since I'm following the instructions.
Here is my subjects_controller.rb file:
class SubjectsController < ApplicationController
def index
list
render('list')
end
# def index
# show
# render('show')
# end
def list
@subjects = Subject.order("subjects.position ASC")
#@subjects = Subject.all
end
def show
@subjects = Subject.find(params[:id])
end
def new
@subjects = Subject.new
end
def create
@subject = Subject.new(params[:subject])
if @subject.save
redirect_to(:action => 'list')
else
render('new')
end
end
end
Here is my list.html and show.html file:
<div class="subject list">
<h2>Subjects</h2>
<table class="listing" summary="Subject list">
<tr class="header">
<th> </th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<% @subjects.each do |subject| %>
<tr>
<td><%= subject.position %></td>
<td><%= subject.name %></td>
<td class="center"><%= subject.visible ? 'yes' : 'no' %></td>
<td class="center"><%= subject.pages.size %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", '#', :class => 'action edit') %>
<%= link_to("Delete", '#', :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
Show.html
<%= link_to("<< Back to list", {:action => 'list'}, :class => 'back-link') %>
<div class="subject show">
<h2>Show Subject</h2>
<table summary="Subject detail view">
<tr>
<th>Name</th>
<td><%= @subject.name %></td>
</tr>
<tr>
<th>Position</th>
<td><%= @subject.position %></td>
</tr>
<tr>
<th>Visible?</th>
<td><%= @subject.visible ? 'true' : 'false' %></td>
</tr>
<tr>
<th>Created</th>
<td><%= @subject.created_at %></td>
</tr>
<tr>
<th>Updated</th>
<td><%= @subject.updated_at %></td>
</tr>
</table>
</div>
And my config/routes.rb file:
Rails.application.routes.draw do
root :to=>"demo#index"
get 'demo/index'
get 'demo/hello'
get 'demo/other_hello'
resources :subjects
get 'subjects/list' => 'subjects#list'
get 'subjects/list' => 'subjects#show'
get 'subjects/create' => 'subjects#create'
The instructor never shows his routes.rb file so I just started using the gets in order to get my actions to work. The resources :subjects wasn't able to take care of everything so I used GET. Also in my subjects_controller I def:index to render list. If I don't do that nothing works at all. I'm obviously new to all of this but love learning about it and any information is appreciated. I have looked at the rails routing from the guides but that hasn't helped me much. Its more the concept/theory of why my links/actions aren't working that I'd be very interested to hear about. Thanks for any info!
Upvotes: 0
Views: 765
Reputation: 1895
It's because you first decleared
resources :subjects
and then the other routes.
In your case the best way to add routes to a resource is the following:
resources :subjects do
collection do
get :list, to: :show
end
end
This will generate:
# rake routes
list_subjects GET /subjects/list(.:format) subjects#show
subjects GET /subjects(.:format) subjects#index
POST /subjects(.:format) subjects#create
new_subject GET /subjects/new(.:format) subjects#new
edit_subject GET /subjects/:id/edit(.:format) subjects#edit
subject GET /subjects/:id(.:format) subjects#show
PATCH /subjects/:id(.:format) subjects#update
PUT /subjects/:id(.:format) subjects#update
DELETE /subjects/:id(.:format) subjects#destroy
Upvotes: 1
Reputation: 1359
The issue is your routes.rb
file. When you specify resources :subjects
you're adding many routes, one of which is get 'subjects/:id' => 'subjects#show'
Since routes take precedence depending on the order you write them (top to bottom) this is overwriting your get 'subjects/list' => 'subjects#list'
line.
You also have many other redundant routes that are being overwritten there.
get 'subjects/list' => 'subjects#list'
get 'subjects/list' => 'subjects#show'
subjects#show won't ever be called because the route calling subjects#list will take precedence
Upvotes: 1
Reputation: 2575
When you specify in routes
resources :subjects
It creates seven actions( index, new, create, create, show, edit, update, destroy)
When you call localhost:3000/subjects
it ask routes where to go. And index
action is called
/subjects
subjects#index
display a list of all subjects
And when you are saying localhost:3000/subjects/list
It expect id
after /subjects
as there are routes mapped to that
localhost:3000/subjects/5
when you will call this it will call show method in controller asking for record with id 5 in database
/subjects/:id
subjects#show
If you want to see all the routes, from console type
rake routes
And if you want to define extra method like list
as below
get 'subjects/list' => 'subjects#list'
and remove all other routes for list
from routes file
And there are many more options to specify routes
and to learn that this is your best friend
http://guides.rubyonrails.org/routing.html
Upvotes: 2