Christoffer Reijer
Christoffer Reijer

Reputation: 1995

Add owner's username to Rails route

I have a model, Playlist, which belongs_to a User. Instead of the routes for playlists to be

/playlists
/playlists/new
/playlists/:id
/playlists/:id/edit

I would like them to be

/:username/playlists
/:username/playlists/new
/:username/:playlist_slug
/:username/:playlist_slug/edit

But, this has to still work:

playlist_path(@playlist)
# NOT: playlist_path(@playlist.user, @playlist)

Since the user of the path is @playlist.user. It is not DRY to repeat this parameter every time I need a path. Besides, it is a risk, since it allows for bogus calls. For example playlist_path(@alice, @bob.playlists.first).

Upvotes: 1

Views: 107

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

FriendlyID is what you want:

#config/routes.rb
resources :users, path: "", only: [] do
   resources :playlists #-> url.com/:user_id/playlists
end

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :playlists

   extend FriendlyID
   friendly_id :username, use: [:slugged, :finders]
end

This will automatically populate the paths and .find methods with the slug value for your @user:

#view
<%= link_to @playlist.name, user_playlist_path(@user, @playlist) %>

#app/controllers/playlists_controller.rb
class PlaylistsController < ApplicationController
   def show
      @user     = User.find params[:user_id]
      @playlist = @user.playlists.find params[:id]
   end
end

--

As per the FriendlyID docs, you'll need to do the following to get it set up:

rails generate friendly_id #-> initializer
rails generate scaffold user name:string slug:string:uniq
rake db:migrate

You'll also want to update your User model to ensure that each record has a slug:

$ rails c
$ User.find_each(&:save)

Upvotes: 0

Karan Purohit
Karan Purohit

Reputation: 2659

I think you are asking for Friendly id and here is its implementation. Hope this helps

Upvotes: 2

Related Questions