+12

Kết nối với cơ sở dữ liệu trong ứng dụng Ruby on Rails

Bài viết này mình đề cập tới một trong các bước cơ bản nhưng cũng rất quan trọng trong qúa trình phát triển một ứng dụng với Ruby on Rails framework. Đó là kết nối tới cơ sở dữ liệu (có thể là MySQL, PostGresql, ...)

Đây là bước cơ bản để bắt đầu phát triển một ứng dụng Rails, tuy nhiên đôi khi cũng gặp phải những vướng mắc nhỏ gây mất thời gian. Trong qúa trình mình làm projects và deploy đã gặp phải một số vướng mắc trong qúa trình kết nối tới cơ sở dữ liệu, do vậy mình viết lại để lần sau tham khảo và cũng để giups rút ngắn thời gian cho các bạn mới bắt đầu cũng bị lỗi như mình.

Việc kết nối tới cơ sở dữ liệu (CSDL) tóm lại được chia ra thành 2 loại là: kết nối tại localhost và kết nối tới một server CSDL khác (remote DB server).

Phần chung (trên cả development và production)

Trước tiên thì trên máy local hay server của bạn phải cài đặt một CSDL (vd: MySQL).

Để thuận tiện cho việc theo dõi và lấy ví dụ, mình tạo một Rails app tên là db-connect-rails

rails new db-connect-rails -d mysql

-d mysql ở trên là mình sử dụng mặc định CSDL là MySQL khi khởi tạo ứng dụng.

Tiếp theo, để kết nối tới DB MySQL trong Rails app chúng ta sử dụng thư viện mysql2.

Đây là một connector giups kết nối Rails app tới MySQL server.

Thêm dòng sau vào Gemfile, chú ý phiên bản của gem.

gem 'mysql2', '~> 0.3.18'

Chạy bundle install để cài đặt Gem.

Trên môi trường development

Việc kết nối vào DB trên local đơn gianr hơn. Chúng ta tập trung vào file config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: <mysql_user_name>
  password: <mysql_user_password>
  socket: /var/run/mysqld/mysqld.sock

development:
  <<: *default
  database: <db_name>

Chúng ta chú ý tới dòng username, passworddatabase. Thay đổi các thông tin cho phù hợp với cấu hình của bạn.

Chú ý là bạn phải gán quyền phù hợp cho mysql user.

Mình ví dụ như sau:

Tạo mysql database, user và gán quyền phù hợp. Ở đây mình gán mọi quyền với demo_db cho user mới tạo.

$ mysql -u root -p

mysql> create user 'demo_user'@'localhost' identified by '12345678';
mysql> CREATE DATABASE `demo_db` CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> grant all privileges on `demo_db`.* to 'demo_user'@'localhost';

Kiểm tra có kết nối được hay không?

$ mysql -u demo_user -p

Nhập password nếu connect thành công thì là okie.

Như vậy file config/database.yml như sau:

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: demo_user
  password: 12345678
  socket: /var/run/mysqld/mysqld.sock

development:
  <<: *default
  database: demo_db

Như vậy đã kết nối tới CSDL trên local. Chạy Rails app để kiểm tra.

$ cd path/to/db-connect-rails

db-connect-rails$ bundle install
db-connect-rails$ rake db:create
db-connect-rails$ rake db:migrate
db-connect-rails$ rails s

Trên môi trường production

Phần này mình chia làm 2 phần nhỏ hơn là khi deploy ứng dụng lên heroku và deploy ứng dụng lên vps (mình mới chỉ làm với gem capistrano)

Deploy ứng dụng lên heroku và connect tới DB remote

Đầu tiên là chúng ta cũng cần phải có 1 DB server riêng (ví dụ là VPS). Trên server này cần cài đặt CSDL (ví dụ: MySQL).

Chú ý: Khi bạn cài đặt MySQL server lên server micro (512M RAM), có thể sẽ bị false do server thiếu hụt RAM trong qúa trình cài đặt. Để khắc phục điều này bạn tạo ra bộ nhớ swap cho server của bạn. (tạo swap 1G cho server 512M RAM).

Tiếp theo, chúng ta cũng cần tạo mysql user, db và gán các quyền thích hợp trên db server.

Chúng ta cũng làm tương tự như phần ở phía trên, tuy nhiên có điểm khác như sau:

Khi tạo mysql user trên db server, cần tạo thêm 1 user cho phép kết nối từ bên ngoài (từ 1 IP định sẵn hoặc bất kỳ IP nào) như sau:

$ ssh tới db server
$ mysql -u root -p

mysql> create user 'demo_user'@'localhost' identified by '12345678';
mysql> create user 'demo_user'@'<IP>' identified by '12345678';
mysql> create user 'demo_user'@'%' identified by '12345678';

Nếu bạn chỉ định IP cho phép kết nối tới db server thì thôi không sử dụng % nữa. Còn nếu bạn cho phép tất cả đều có thể connect được thì dùng %.

Tiếp theo là tạo db và gán quyền:

mysql> CREATE DATABASE `demo_db` CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> grant all privileges on `demo_db`.* to 'demo_user'@'localhost';
mysql> grant all privileges on `demo_db`.* to 'demo_user'@'<IP> or %';

Thêm một điểm nữa là cần phải sửa file cấu hình của mysql server. Mở file /etc/mysql/my.cnf và tìm tới dòng sau:

bind-address            = 127.0.0.1
sửa lại thành
bind-address            = <IP bạn cho phép remote tới>
hoặc
bind-address            = 0.0.0.0

Nếu để như dòng cuối thì cho phép tất cả có thể remote tới được.

Kiểm tra kết nối. Tại local nếu bạn để 0.0.0.0 hoặc từ địa chỉ <IP>

$ mysql -u demo_user -h <db server IP> -p

Nếu kết nối thành công thì tiếp tục.

Tiếp theo là deploy Rails app lên Heroku.

Thêm dòng sau vào Gemfile

group :production do
  gem 'pg',             '0.17.1'
  gem 'rails_12factor', '0.0.2'
end

Chạy lệnh sau để cài đặt gem:

bundle install --without production

Add và commit changes:

$ git add -A
$ git commit -m "Deploy to heroku"

Phần này mình coi như bạn đã đăng ký tài khoản heroku và cài đặt heroku tool trên local rồi.

Chạy lệnh sau để kiểm tra heroku đã cài trên local (nó sẽ tự động update nếu đã cài)

heroku version

Đăng nhập vào tài khoản heroku của bạn:

heroku login

Add ssh keys

heroku keys:add

Tạo heroku app:

heroku create

Deploy code to heroku

git push heroku master

Chú ý: kể từ những lần deploy code sau thêm -f vào sau lệnh trên.

Deploy thành công có dạng như sau:

remote: Verifying deploy... done.
To https://git.heroku.com/floating-glad-9.git
   7102f50..8176d27  master -> master

Tuy nhiên khi deploy thành công như trên, app của bạn đang sử dụng db mặc định mà heroku tạo cho.

Để biết về database đó bạn có thể xem trên web. Hoặc chạy lệnh sau để biết về đường dẫn tới db server đó:

heroku config

Khi đó bạn thấy 1 dòng định dạng như sau:

DATABASE_URL: postgres://uaavacmcvvbgce:HYNYgB6mGvcdasBu_TzZ_sENt4CGB@ec2-54-83-3-38.compute-1.amazonaws.com:5432/dd33pk1bjapdt

Đây là url db server heroku tạo mặc định cho bạn. Tuy nhiên ở đây chúng ta muốn kết nối Rails app của chúng ta tới db server riêng như đã cấu hình mysql user, db name ở trên.

Do vậy, chúng ta cần thay đổi DATABASE_URL ở trên thành đường dẫn tới database trên server của ta.

Để thay đổi biến môi trường, heroku cung cấp các lệnh như sau:

heroku config:set
heroku config:get
heroku config:unset

Tuy nhiên với biến môi trường DATABASE_URL thì không thể set lại được. Ví dụ khi bạn chạy lệnh sau để thay đổi nó:

heroku config:set DATABASE_URL="Test"

Sẽ có lỗi như sau:

Cannot overwrite attachment values DATABASE_URL.

Vậy, để giải quyết được lỗi trên mình làm như sau:

heroku addons:attach <heroku-postgresql_db_name> -a <app_name>
heroku addons:detach DATABASE -a <app_name>
heroku config:add DATABASE_URL=

Đường dẫn tới db server của mình như thế nào?

Nó có định dạng như sau:

<adapter>://<mysql_user>:<mysql_user_password>@<db_server_IP>:[port]/<db_name>?[options]

Như ở trên thì chúng ta đã sử dụng mysql2 làm adapter connect tới db server.

DATABASE_URL như sau:

mysql2://demo_user:12345678$<db_server_IP>:3306/demo_db

Như vậy là chúng ta đã kết nối Rails app sử dụng heroku host và database riêng.

Deploy lên server VPS

Phần này mình sử dụng gem capistrano để deploy Rails app lên VPS.

Để kết nối tới db server từ rails app đã deploy lên VPS đơn gian hơn so vơi heroku, nó tương tự như với local.

Các bước thiết lập mysql user, db và cho phép connect từ xa làm tương tự như phần deploy lên heroku bên trên.

Để kết nối tới db server thì chúng ta sửa file `config/database.yml' như sau:

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  socket: /var/run/mysqld/mysqld.sock

...

production:
  <<: *default
  host: <db_server_IP>
  username: demo_user
  password: 12345678
  database: demo_db

Push code lên git và deploy lại. Việc kết nối là hoàn tất.

Trên đây là bài viết thu lại được trong qúa trình mình làm phần này. Mong giups ích được cho các bạn mới bắt đầu với nó. 😄


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.