Using PostgreSQL and jsonb with Ruby on Rails
Bài đăng này đã không được cập nhật trong 7 năm
Trong một ứng dụng Rails, chúng ta thường xuyên có các chức năng thiết lập riêng của từng ngường dùng ví dụ city, tài khoản mạng xã hội, blog, theme v.v... Hiện nay, đã có rất nhiều phương pháp để thực hiện lưu trữ những thông tin này vào trong cơ sở dữ liệu quan hệ. Phương pháp phổ biến nhất mà mọi lập trình viên đều biết đó là ứng với mỗi thiết lập sẽ tạo một cột trong bảng User của cơ sở dữ liệu hay thậm chí là có một bảng riêng để lưu trữ thông tin trên... Tuy nhiên, với việc phiên bản Postgres 9.4 bổ sung thêm kiểu dữ liệu jsonb, ta có thêm một phương pháp khác đó là lưu trữ tất cả các thông tin user setting chỉ vào một cột trong bảng. Kết hợp với việc sử dụng gem Storext, ta sẽ có được một cách lưu trữ dữ liệu thiết lập của người dùng một cách đơn giản. Trong bài viết này, tôi xin trình bày về cách thực hiện của phương pháp này
Requirements
- Postgres 9.4+
- Rails 4.x+
Tạo cột preferences trong bảng users
Ta tạo một cột có tên là preferences có kiểu là jsonb trong bảng users bằng một trong hai cách sau:
# db/migrate/*_create_users.rb
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.text :name, null: false
t.jsonb :preferences, null: false, default: '{}'
end
add_index :users, :preferences, using: :gin
end
end
# db/migrate/*_add_jsonb_column_to_users.rb
class AddJsonbColumnToUsers < ActiveRecord::Migration
def change
add_column :users, :preferences, :jsonb, null: false, default: {}
add_index :users, :preferences, using: :gin
end
end
Sau đó chúng ta phải chạy lệnh rake db:migrate
để có thể tạo cột trong cơ sở dữ liệu
Cài đặt gem Storext#
Đến đây, cột preferences
của bạn sẽ lưu trữ dữ liệu giống json trong Postgres, nhưng chúng ta muốn cột này được xử lý giống như những cột bình thường khác (integer, text) trong ActiveRecord::Base
thì gem storetext
là một lựa chọn trên cả tuyệt vời. Việc cài đặt gem này hết sức đơn giản. Ta chỉ cần add gem 'storext' vào Gemfile rồi chạy bundle install.
Thêm cấu hình cho cột preferences
Đây là một phần thú vị, tất cả mọi cấu hình đều được định nghĩa qua phương thức store_attributes
của gem Storext. Để cấu hình cho cột preferences
, ta có thể thực hiện giống như sau:
class User < ActiveRecord::Base
include Storext.model
# "preferences" matches what we named the database column
store_attributes : preferences do
twitter String
github String
blog String
city String
newsletter Boolean, default: true
end
end
Đến đây, ta có thể sử dụng các biến twitter
, blog
... như một attribute bình thường trong ActiveRecord::Base của Rails. Ví dụ:
User.new blog: "http://example.com", github: "luongvietdung"
Một điều hết sức thú vị khác đó là chúng ta vẫn sử dụng được các validate chuẩn của Rails với các attributes blog
, github
... ngoại trừ validate unique. Điều đó có nghĩa là ta hoàn toàn có thể khai báo như sau trong model User
:
class User < ActiveRecord::Base
[...]
validates :github, presence: true
[...]
end
Truy vấn với jsonb
Một trong những tác vụ quan trọng nhất của cơ sở dữ liệu là truy vấn. Vậy đối với kiểu jsonb thì ta sẽ phải thực hện truy vấn ra sao?. Các bạn không nên lo lắng, PostgreSQL đã cung cấp một số toán tử cơ bản phục vụ cho việc viết truy vấn tại đây. Sau đây tôi xin đưa ra một vài ví dụ truy vấn đơn giản đối với cột jsonb :
- Lấy danh sách những user có
newsletter = true
:
User.where('preferences @> ?', {newsletter: true}.to_json)
- Lấy danh sách những user đã có thông tin tài khoản Github và Twitter
User.where('preferences ?& array[:keys]', keys: ['twitter', 'github'])
- Lấy danh sách những user đã có thông tin tài khoản Github hoặc Twitter
User.where('preferences ?| array[:keys]', keys: ['twitter', 'github'])
- Lấy danh sách những user sống tại thành phố Hà Nội
User.where('preferences @> ?', {city: 'Hà Nội'}.to_json)
Kết luận#
Như vậy, trên đây tôi đã giới thiệu một kiểu dữ liệu đặc biệt trong PostgreSQL 9.4+ đó là jsonb để sử dụng trong trường hợp lưu trữ user settings vào cùng một trường. Đây có thể nói là một phương pháp đơn giản, dễ xử lý và tường minh. Tài liệu tham khảo:
- https://medium.com/@mscccc/rails-storing-user-settings-2016-edition-443c5ea5a921#.ruqqr0yr3
- https://github.com/G5/storext
Xin cảm ơn mọi người đã theo dõi bài viết. Lời cuối cùng xin gửi tới mọi người lời chúc mừng năm mới!
All rights reserved