Sam Gruse
Sam Gruse

Reputation: 488

CRUD in ruby on rails. Routing

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>&nbsp;</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

Answers (3)

bukk530
bukk530

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

Mario
Mario

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

Sonalkumar sute
Sonalkumar sute

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

Related Questions