Friendly URLs với gem Friendly_id trong Rails

Giới thiệu

Chắc hẳn các bạn vừa mới tiếp xúc với Ruby on Rails như mình cũng sẽ có thắc mắc rằng URLs của app mình không giống như những trang web trên mạng. Mình xin đưa ra 2 ví dụ như sau: http://localhost:3000/subjects/1/chapters/1 là URL mặc định mà Rails xây dựng dựa trên primary key-cột id từ database. và http://localhost:3000/ruby-on-rails/chapter-1 là URL như những trang web trên mạng. Một URL như thế này được gọi là một friendly url. Mô tả ngắn gọn cho user về trang mà chúng ta sẽ chuyển đến, ngoài ra URL chứa từ khóa sẽ làm tăng giá trị của bài viết vì trong SEO, đường dẫn URL tốt sẽ giúp cho Google index dễ dàng hơn. Tức là người dùng có thể dễ dàng tìm kiếm thấy bài viết của các bạn hơn. Trong bài viết này mình sẽ giới thiệu về chủ đề này, mặc dù nó không mới và cũng không khó nhưng mình thấy nó cần thiết cho 1 website.

Cài đặt

Thêm gem này vào gemfile và chạy bundle install. gem "friendly_id", "~> 5.1.0" bundle

Tạo file config rails generate friendly_id Thêm column vào bảng Subject trong database rails generate migration AddSlugToSubjects slug:string Sau đó chỉnh sửa thêm index cho migration file như sau:

class AddSlugToSubjects < ActiveRecord::Migration[5.1]
  def change
    add_column :subjects, :slug, :string
    add_index :subjects, :slug
  end
end

rails db:migrate

Nếu các bạn dùng Rails 5.1+, trước khi chạy rails db:migrate các bạn vào file migration mới tạo và chỉ định version cho nó. Sửa class CreateFriendlyIdSlugs < ActiveRecord::Migration thành class CreateFriendlyIdSlugs < ActiveRecord::Migration[5.1] rồi chạy rails db:migrate

Sửa file app/models/subject.rb như sau:

class Subject < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged
end

Sử dụng

Trong file app/controllers/users_controller.rb sửa Subject.find_by thành Subject.friendly.find_by

class SubjectController < ApplicationController
  def show
    @subject = Subject.friendly.find_by id: params[:id]
  end
end
  • Hoặc ta cũng có thể cấu hình như sau để giảm sự lặp lại code trong project. Thêm option :finders vào Subject model friendly_id :name, use: %i(slugged finders) Sau khi thêm thì lúc gọi ta chỉ cần gọi như sau: @subject = Subject.find_by id: params[:id]
  • Khi sử dụng với gem cancancan, chúng ta cần config lại như sau. load_and_authorize_resource find_by: :slug

Test thử:

Subject.create! name: "Ruby on Rails"
Subject.friendly.find_by_slug "ruby-on-rails"    #=> Có hoạt động
Subject.friendly.find_by id: 1                   #=> Vẫn hoạt động
Subject.find_by id: 1                            #=> Vẫn hoạt động
Subject.find("ruby-on-rails")                    #=> Không hoạt động

Bây giờ, url trang show của subject này là http://localhost:3000/subjects/ruby-on-rails Tương tự với chapter các bạn sẽ được url là http://localhost:3000/ruby-on-rails/chapter-1

Generate new slugs

Khi chúng ta tạo mới một subject hoặc khi ta update lại trường name chúng ta cần override lại method _should_generate_new_friendly_id? như dưới đây.

class Subject < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged

  def should_generate_new_friendly_id?
    name_changed? || super
  end
end

Nguồn tham khảo

https://github.com/norman/friendly_id

Kết luận

SEO là một công việc đòi hỏi sự kết hợp, tương tác nhuần nhuyễn nhiều thủ thuật khác nhau. Và Pretty URL là một trong những kỹ thuật đó, hy vong bài viết giúp ích được cho công việc các bạn.

Cảm ơn các bạn đã xem!