📚 Blog Archive

A Social Network in Rails: Elegant permalinks

· Miguel Parramón · blogger

In this post we’re adding permalinks to a Rails app using the friendly_id gem.

Let’s say you have a `User` and a `Photo` model in your app, and a user has_many :photos.
To add a permalink to a photo post that looks like this:
www.nice-pics.com/berners-lee/photos/my-first-site

Add friendly_id to your Gemfile:

gem “friendly_id”

Add the permalink schema to your routes.rb:

get “:user_id/photos/:photo_id”, to: “photos#show”, as: :photo_permalink

Now, add the friendly_id scheme to your User:

class User::HasFriendlyId < ActiveRecord::Base extend FriendlyId friendly_id :slug_candidates

has_many :photos

def slug_candidates # if there’s a username clash, use the full email [:username, :email] end

def username email.split(”@“).first end
end

and to your Photo:

class Photo < ActiveRecord::Base include Rails.application.routes.url_helpers extend FriendlyId friendly_id :slug_candidates, use: :scoped, scope: :user

belongs_to :user

def slug_candidates # if there’s a name clash, use the photo’s name, width & height [:name, -> { ”#{name}-#{width}-#{height}” }] end

def permalink photo_permalink_url( user_id: user.friendly_id, photo_id: friendly_id, host: “https://www.example.com” ) end end

Add the slugs to your db via migrations:

rails generate migration add_slug_to_photo slug:string rails generate migration add_slug_to_user slug:string

And finally, add the controller action:

class ClipsController < ApplicationController def show user = User.friendly.find(params[:user_id]) @clip = user.photos.friendly.find(params[:clip_id]) end end

Done! Now, if you do in your Rails console:

> user = User.create(email: berners-lee@internet.org)

user.photos.create(name: my-first-site, width: 200, height: 300)

The following link will work: www.nice-pics.com/berners-lee/photos/my-first-site
And, if we add another photo with the same name, its link will still look nice:

> user.photos.create(name: my-first-site, width: 400, height: 800)

www.nice-pics.com/berners-lee/photos/my-first-site-400-800

Human readable, clear, and permanent. Nice :D

View original post →