Alex Liang

[Rails] 使用friendly_id增加URL可讀性

在預設的routing和URL中,每筆資料皆以id做查詢及顯示。
例如網站有個post model及controller,則第一則post id為1,其URL為/posts/1。
這對網站SEO及可讀性來說是很糟糕的做法。

如果要使用有意義的欄位(例如post title)作為URL的一部分,我們可以覆寫to_param並使用parameterize將id加上post title

app/models/post.rb
1
2
3
4
5
class Post < ActiveRecord::Base
def to_param
"#{id}-#{title}".parameterize
end
end

透過此方法,假如第一則post title為rails routing,則本來的//post/1會變成//post/1-rails-routing。
但這樣還是有id number在URL。想更進一步去除id,需要在post model加入名為slug的欄位

1
2
>> rails g migration AddSlugToPosts slug
>> rake db:migrate

修改post model

app/models/post.rb
1
2
3
4
5
6
7
8
9
10
11
class Post < ActiveRecord::Base
before_save :update_slug

def update_slug
self.slug = title.parameterize # 在儲存post前,先將title參數化存到slug
end

def to_param
slug
end
end

app/controllers/posts_controller.rb
1
2
3
4
5
6
7
class PostsController < ActionController	
... 略

def find_params
@post = Post.find_by_slug(params[:id]) # 由於id在to_param時己改為slug,找資料時得用slug
end
end

以上介紹的方法最大的問題是當title被更改後(例如rails routing 2),則URL會成為//posts/rails-routing-2
舊的網址將會失效,這對使用者來說會是非常不便的事。

因此介紹friendly_id這套gem,它能幫我們把URL變美觀,且省下很多力氣

Install

Gemfile
1
gem 'friendly_id', '~> 5.1.0' # Note: You MUST use 5.0.0 or greater for Rails 4.0+

接著bundle install以完成安裝

1
2
>> rails generate friendly_id
>> rake db:migrate

Model and Controller

app/models/post.rb
1
2
3
4
5
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
... 略
end
app/controllers/posts_controller.rb
1
2
3
4
5
6
7
class PostsController < ActionController	
... 略

def find_params
@post = Post.friendly.find(params[:id])
end
end

將本來的find前面加上friendly這個method,才能找到資料。

參考來源:
Friendly ID介紹影片
friendly_id github