Config multiple databases in Rails
Bài đăng này đã không được cập nhật trong 6 năm
Khi dự án của bạn yêu cầu xây dựng database cho một ứng dụng cho phép chia sẻ một vài dữ liệu chung cho một vài sites khác. Ví dụ như là chúng ta có 2 ứng dụng là notes
và memories
cần dùng chung database là bảng user
để khi mà người dùng có tài khoản trong notes
thì đều có thể đăng nhập vào memories
thông qua tài khoản đó trong khi đó chúng ta cũng có những database riêng để lưu trữ dữ liệu cho những phần khác của những sites đó. Vậy chúng ta cần phải làm gì?
Đến đây chắc bạn cũng sẽ nghĩ cần phải tách dữ liệu và lưu trữ vào những database riêng biệt, qua đó có thể include vào những sites khác nhau để dùng. Vậy làm sao để có thể sử dụng multiple database trong ứng dụng, dưới đây mình sẽ hướng dẫn config và migration multiple databases trong Rails application. Bài hướng dẫn sử dụng Rails 4.x
Đầu tiên để ứng dụng có thể hoạt động ta cần configure database connection và mọi việc này hoàn toàn có thể nằm trong 1 file duy nhất là database.yml
. Có rất nhiều cách khác nhau để config các database, ở đây mình sẽ giới thiệu cách mà mình thấy là rõ ràng và có thể biểu hiện được multi database ở đây. Chúng ta có 2 database là db1
và db2
sẽ config như sau:
# config/database.yml
defaults: &defaults
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
collation: utf8_unicode_ci
socket: /var/run/mysqld/mysqld.sock
db1:
development:
database: db1_development
<<: *defaults
test:
database: db1_test
<<: *defaults
production:
database: db1_production
<<: *defaults
db2:
development:
database: db2_development
<<: *defaults
test:
database: db2_test
host: localhost
<<: *defaults
production:
database: db2_production
host: localhost
<<: *defaults
development:
database: db1_development
<<: *defaults
test:
database: db1_development
<<: *defaults
Lưu ý, nhìn bên trên kia bạn vẫn thấy có config development đúng không? Đừng bận tâm nhiều đến nó, vì đó chỉ là một khai báo mặc định app sẽ nhận nó, còn lại chúng ta sẽ sử dụng những config trong db1
và db2
để tiến hành migration và connect để sử dụng.
Tiếp đó chúng ta sẽ định nghĩa constants cho config của db1
và db2
để có thể dễ dàng sử dụng ở tất cả mọi nơi cần dùng (migration và model), ta có thể định nghĩa chúng trong application.rb
# config/application.rb
module MultiMysql
db_conf = YAML.load_file("config/database.yml")
DB1_CONF = db_conf["db1"][Rails.env]
DB2_CONF = db_conf["db2"][Rails.env]
....
end
Tiếp đến chúng ta sẽ xử lý phần migration. Đầu tiên, bạn tạo các file migration như bình thường, có thể sử dụng lệnh rails g model ...
của rails sẽ tạo ra file migration như bình thường, sau đó bạn sẽ thêm vào mỗi file @connection
để biết được là mình đang connect đến database nào, muốn cho bảng đó nằm trong database nào thì ta connect đến database đó. Hay để dễ quản lý, mình sẽ chia migration ra làm 2 folder riêng biệt, 1 lưu trữ migration file cho database 1 được đặt tên là db1
và cái còn lại sẽ lưu trữ migration file cho database 2 với tên là db2
. Sau đó mình sẽ tạo file base cho mỗi db1
và db2
trong đó có chứa connection kết nối tới Mysql của db1
và db2
. Ví dụ file migration của db1
# db/migrate/db1/db1_migration_base.rb
class Db1MigrationBase < ActiveRecord::Migration
protected
def change
@connection = ActiveRecord::Base.establish_connection(MultiMysql::DB1_CONF).connection
end
end
# db/migrate/db1/20160505121212_create_users.rb
require_relative './db1_migration_base'
class CreateUsers < Db1MigrationBase
def change
super
create_table :users do |t|
t.string :name
t.string :email
t.timestamps null: false
end
end
end
Giờ, nếu muốn thêm bảng nào vào db1
bạn cũng chỉ cần tạo file migration như bình thường sau đó chuyển file đó vào thư mục db1
và cho nó kế thừa từ Db1MigrationBase
sử dụng super
function change
để có connection đến config db1
và sử dụng như bình thường.
Một điều lưu ý là bạn cần tạo database bằng tay, không như database bình thường là chúng ta chỉ cần dùng lệnh rake db:create
vì nó sẽ chỉ tạo database config trong development
. Giờ bạn có thể dùng lệnh rake db:migrate
như bình thường. Sau khi migration xong ta có thể kiểm tra database trong mysql, thu được kết quả như sau:
Cuối cùng, ta sẽ nói cho model biết connect đến database nào bằng cách sử dụng establish_connection
của ActiveRecord
.
# app/models/user.rb
class User < ActiveRecord::Base
establish_connection MultiMysql::DB1_CONF
has_many :products
end
# app/models/product.rb
class Product < ActiveRecord::Base
establish_connection MultiMysql::DB2_CONF
belongs_to :user
end
Chúng ta hoàn toàn có thể sử dụng association bình thường.
User.first.products
User Load (0.4ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
Product Load (0.6ms) SELECT `products`.* FROM `products` WHERE `products`.`user_id` = 1
Vậy là xong, bây giờ bạn có thể config bao nhiêu database tùy ý.
Reference
Ruby on Rails Connect to Multiple Databases and Migrations Multiple-Databases In Single Rails Application Connecting Models To Different Databases In Rails
Demo
All rights reserved