Sử dụng Hash IDs cho URL với Ruby on Rails
Khi phát triển ứng dụng web của bạn với Ruby on Rails, bạn thường gặp và sử dụng ID trong URL của bạn (/articles/1, articles/1/edit, ...). Thường đây là id auto-increment ở trong database. Để tạo thêm sự an toàn hơn, tránh việc dự đoán được từ phía users, mình nên sử dụng url format khác như sử ...
Khi phát triển ứng dụng web của bạn với Ruby on Rails, bạn thường gặp và sử dụng ID trong URL của bạn (/articles/1, articles/1/edit, ...). Thường đây là id auto-increment ở trong database. Để tạo thêm sự an toàn hơn, tránh việc dự đoán được từ phía users, mình nên sử dụng url format khác như sử dụng format text hoặc UUIDs, Hash IDs.... Hôm này mình xin giới thiệu một kỹ thuật là cách sử dụng Hash IDs cho URL.
- Ở đây mình sẽ sử dụng gem https://github.com/norman/friendly_id gem "friendly_id" giúp bạn tạo url với những format khác nhau như kiểu text (slug), hoặc custom format khác, ... Ở đây mình sẽ sử dụng gem này để customize url thành dạng Hash IDs.
# Gemfile gem 'friendly_id', '~> 5.1.0'
bundle install
- Thêm column hash_id vào model:
class AddHashIdToTable < ActiveRecord::Migration[5.0] def change add_column :hash_id, :table_name, :string, index: true end end
- Tạo model concern: module này dùng để generate ra Hash IDs cho model trước khi lưu vào db. Mỗi hash_id trong db phải khác nhau, vậy trước khi lưu vào db, phải kiểm tra và đảm bảo là hash_id đó là chưa có.
# app/models/concerns/friendlyable.rb module Friendlyable extend ActiveSupport::Concern included do extend ::FriendlyId before_create :set_hash_id friendly_id :hash_id end def set_hash_id hash_id = nil loop do hash_id = SecureRandom.urlsafe_base64(9).gsub(/-|_/,('a'..'z').to_a[rand(26)]) break unless self.class.name.constantize.where(:hash_id => hash_id).exists? end self.hash_id = hash_id end end
- Bây giờ mình đã có module để generate ra hash_id rồi, tiếp theo mình phải include module đó vào trong những model mình cần tạo hash_id.
class User < ApplicationRecord include Friendlyable ... end
- Đến đây bạn đã có hash_id cho urls rồi, bây giờ url của bạn sẽ thành dạng như sau: http://localhost:3000/users/90upoijsz Tiếp theo để tìm records, mình sẽ sử dụng như sau:
User.friendly.find(params[:id])
Thay vì tìm theo id, bây giờ sẽ tìm theo hash_id.
Bạn có thể tham khảo chi tiết hơn: https://github.com/norman/friendly_id https://hackernoon.com/how-to-use-hash-ids-in-your-url-in-ruby-on-rails-5-e8b7cdd31733 http://norman.github.io/friendly_id/