Search code examples
ruby-on-railsmodelrails-routingactiveresource

Rails routing when nesting resources


I'm trying to figure out how to specify the route I'm trying to use but I keep getting routing errors. Can someone please point out where I'm going wrong and maybe explain what a better way to do this might be?

I'm working with these (nested) resources:

resources :users do
  resources :playlists
end

Models:

class User < ActiveRecord::Base
  has_many :playlists
end

class Playlist < ActiveRecord::Base
    belongs_to :user
    validates :user_id, presence: true
end

Now I'm trying to link to a user's playlists inside the user/show.html.erb file:

<p>
  <%= link_to "Playlists", user_playlists_path(@playlist)%></p>
</p>

Which brings me to a Playlists page (/users/1/playlists) successfully but when I try adding a new playlist for this user, I get the following error:

Showing /app/views/playlists/_form.html.erb where line #1 raised:

undefined method `playlists_path' for #<#<Class:0x0000000335c688>:0x00000003d0b238>

This is line #1:

 <%= form_for(@playlist) do |f| %>

This is what I get for rake routes if that helps at all:

            Prefix Verb   URI Pattern                                  Controller#Action
    user_playlists GET    /users/:user_id/playlists(.:format)          playlists#index
                   POST   /users/:user_id/playlists(.:format)          playlists#create
 new_user_playlist GET    /users/:user_id/playlists/new(.:format)      playlists#new
edit_user_playlist GET    /users/:user_id/playlists/:id/edit(.:format) playlists#edit
     user_playlist GET    /users/:user_id/playlists/:id(.:format)      playlists#show
                   PATCH  /users/:user_id/playlists/:id(.:format)      playlists#update
                   PUT    /users/:user_id/playlists/:id(.:format)      playlists#update
                   DELETE /users/:user_id/playlists/:id(.:format)      playlists#destroy
             users GET    /users(.:format)                             users#index
                   POST   /users(.:format)                             users#create
          new_user GET    /users/new(.:format)                         users#new
         edit_user GET    /users/:id/edit(.:format)                    users#edit
              user GET    /users/:id(.:format)                         users#show
                   PATCH  /users/:id(.:format)                         users#update
                   PUT    /users/:id(.:format)                         users#update
                   DELETE /users/:id(.:format)                         users#destroy
              root GET    /                                            default_pages#home
            signup GET    /signup(.:format)                            users#new
            signin GET    /signin(.:format)                            users#signin

Solution

  • The errors:

    undefined method `playlists_path' for #<#<Class:0x0000000335c688>
    

    and

    user_playlist GET /users/:user_id/playlists/:id(.:format)

    Gives a clear reason of the error you have.

    <%= form_for(@playlist) do|f| %>
    

    should be

    <%= form_for([@user, @playlist]) do|f| %>
    

    Or current_user, what is important is you need to pass the user object.

    Explanation :

    If you have noticed in a update action (taking that you redirect to a show page after you update) instead of redirect_to user_path(@user) we can do just redirect_to @user, from which Rails infers that you are redirecting to the show path of user.

    It is a similar situation here, similarly if you are having a form_for for the playlist and you pass only @playlist instead of [@user, @playlist] then it woud try to find new_playlist_path, which isn't in your route and will show an error.

    This is a short gist on how you might do it.