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 ...
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).
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.
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, password và database. 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
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ó.