Setting up Rails 5.2 Active Storage, sử dụng Google Cloud Storage và Heroku
Bài đăng này đã không được cập nhật trong 5 năm
Mục đích của tutorial này là tạo một rails app "To do", đính kèm ảnh và các tập tin khác vào Google Cloud Storage, sử dụng Rails Active Storage, cuối cùng, deploy app lên Heroku thông qua git. Chỉ cần có các kiến thức cơ bản về Rails và git, bạn hoàn toàn thể thực hiện được từng bước theo bài viết.
Đầu tiên, cần chắc chắn bạn đã cài đặt đúng version. Chúng ta cần Rails 5.2, vì từ phiên bản này mới có Active Storage, và cần Ruby từ version 2.2.2 trở lên.
rails -v
ruby -v
Và nếu tất cả đã sẵn sàng, hãy tạo một Rails app:
rails new todo-pic
cd todo-pic
Bắt đầu bằng việc tạo model Todo, controller, view và migate database:
rails generate scaffold Todo task:string
rails db:migrate
setup root trong file config/routes.rb
root "todos#index"
khởi động server
rails server
Giờ vào địa chỉ http://localhost:3000
, trang web của chúng ta sẽ tựa tựa thế này:
Vậy là xong công tác chuẩn bị, tiếp theo sẽ là cách để đính kèm ảnh.
Setup Active Storage
Trong bước đầu tiên này Rails sẽ tạo 2 bảng trong database là active_storage_blobs
và active_storage_attachments
. Nó cũng tạo ra file config storage.yml
nhưng chúng ta sẽ nói đến nó sau.
rails active_storage:install
rails db:migrate
Thiết lập 1 tập đính kèm
has_one_attached
sẽ setup mối quan hệ 1 - 1 giữa bản ghi và file đính kèm. Mỗi bản ghi chỉ có thể chứa 1 file đính kèm. Trong ví dụ này, sẽ là 1 ảnh đính kèm với 1 todo
.
Sửa lại Model:
# app/models/todo.rb
class Todo < ApplicationRecord
has_one_attached :picture
end
Sửa lại Controller thêm param :picture
# app/controllers/todos_controller.rb
def todo_params
params.require(:todo).permit(:task, :picture)
end
Sửa lại view: trong form, tạo một thẻ input file_field
, phía trên nút submit:
# app/views/todos/_form.html.erb
...
<div class="field">
<%= form.label :picture %>
<%= form.file_field :picture %>
</div>
...
Trong trang show
, hiển thị imge với thẻ image_tag
, quy ước chiều rộng 200px, và thêm điều kiện if kiểm tra có tệp đính kèm hay không, phương thức attached?
sẽ trả về true nếu có tệp đính kèm.
# app/views/todos/show.html.erb
...
<p>
<%= image_tag(@todo.picture, width: 200) if @todo.picture.attached? %>
</p>
...
Vậy là xong.
Setup nhiều tệp đính kèm
Giờ ta muốn đính kèm nhiều tập tin vào todo
. has_many_attached
sẽ setup mối quan hệ 1 - n giữa record và tệp đính kèm. Mỗi bản ghi có thể có nhiều tệp đính kèm.
Sửa lại model:
# app/models/todo.rb
class Todo < ApplicationRecord
...
has_many_attached :uploads
end
Sửa lại controller: có nhiều tập tin nên ta phải truyền param vào dưới dạng mảng
# app/controllers/todos_controller.rb
...
def todo_params
params.require(:todo).permit(..., uploads: [])
end
...
Sửa lại view: trong form, thêm thẻ input file_field
cho phép upload nhiều file, bằng cách thêm option multiple: true
# app/views/todos/_form.html.erb
...
<div class="field">
<%= form.label :uploads %>
<%= form.file_field :uploads, multiple: true %>
</div>
...
Và trong trang show, chúng ta sẽ hiển thị tất cả file được upload. Nếu không có gì, message no uploads
sẽ hiện ra.
# app/views/todos/show.html.erb
...
<p>
<strong>Uploads:</strong> <br/>
<% if @todo.uploads.attached? %>
<% @todo.uploads.each do |upload| %>
<%= link_to upload.filename, upload, target: '_blank' %> <br/>
<% end %>
<% else %>
<p>no uploads</p>
<% end %>
</p>
...
Vậy là xong, bạn có thể test thử upload nhiều file.
Nãy giờ, chúng ta vẫn lưu vào local, phần tiếp theo sẽ nói về cách sử dụng Google Cloud Service để lưu trữ các tập tin.
Lưu ý: trước khi sang phần sau cần xóa hết các bản ghi và tệp đính kèm vừa tạo (hoặc reset database) để tránh gặp lỗi khi sửa lại config.
Google cloud services (GCS)
Bắt đầu bằng việc tạo 1 account, nếu bạn chưa có. Bạn có thể tạo miễn phí, và dùng thử 1 năm dịch vụ professional. Ở Console tạo project "Todo-pic" (hoặc bất kì tên gì bạn thích)
Bước tiếp theo là tạo "bucket", nơi lưu trữ dữ liệu. Click vào Storage:
Sau đó click vào Create bucket:
Giờ bạn có thể chọn một cái tên cho bucket của mình, lưu ý là nó phải là cái tên chưa từng được sử dụng trên Cloud Storage. Chọn storage class là Regional và a server zone (ví dụ us-east1), rồi ấn Create:
Bucket đã được tạo, nhưng giờ bạn cần truy cập nó. Google cung cấp sẵn API để làm điều đó, nhưng bạn cần tạo Credentials:
Chọn APIs and Services và Credentials:
Tạo ‘Service account key’ để enable giao tiếp server-to-server.
Chọn tên account. Chọn role Project/Owner, và key type JSON. Sau đó click ‘Create’.
Khi bạn click Create, private key sẽ được download về máy tính của bạn.
Giờ bắt đầu setup Rails app để làm việc với Google Cloud Bucket. Bắt đầu bằng cách tạo folder secrets
trong folser config/
. Sau đó thêm /config/secrets/*
vào file .gitignore
. Nó sẽ ngăn chặn việc folder secrets
bị upload lên git remote.
Tiếp theo di chuyển file .json vừa download về vào folder config/secrets/
. Đổi tên nó thành todo-pic.json
.
Mở file config/storage.yml
, đây là file lưu trữ các config, bạn có thể thấy service test:
và local:
được lưu làm mặc định. Thêm config service google:
, sử dụng tên project và bucket của bạn.
# config/storage.yml
google:
service: GCS
project: todo-pic
credentials: <%= Rails.root.join("config/secrets/todo-pic.json") %>
bucket: todo-pic-pjbelo
Giờ sửa file config/environments/development.rb
để Rails biết bạn muốn sử dụng google:
ở môi trường development.
# config/environments/development.rb
config.active_storage.service = :google
Chúng ta cần thêm gem google-cloud-storage vào gemfile làm thư viện cho Google Cloud Storage.
#Gemfile
gem "google-cloud-storage", "~> 1.8", require: false
và chạy bundle install
.
Giờ mọi thứ đã sẵn sàng! Chạy server và test thử tính năng upload. Bạn có thể check trong Google Cloud Platform / Bucket số lượng file được upload.
Heroku
Hãy bắt đầu bằng việc tạo 1 account, nếu bạn chưa có. Sau đó cài Heroku CLI.
Sửa lại file config/environments/production.rb
để nói cho hệ thống bạn muốn sử dụng google:
ở môi trường production.
config.active_storage.service = :google
Login vào Heroku bằng cách chạy lệnh heroku login
.
Config database
Phần mềm quản lý database mặc định của Rails là SQLite, nhưng Heroku không làm việc với nó. Heroku khuyên nên sử dụng PostgreSQL và nên sử dụng cùng 1 loại phần mềm quản lý database cho môi trường development và production, hạn chế những bug phát sinh do khác biệt giữa các phần mềm. Trong bài viết này thì vẫn sử dụng SQLite ở môi trường development, nhưng đừng làm vậy ở dự án thực tế nhé.
Để sử dụng PostgreSQL ở môi trường production thì phải thêm vào Gemfile:
#Gemfile
group :production do
gem 'pg'
end
Và dời development và test vào cùng 1 group:
group :development, :test do
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
...
sau đó lại chạy bundle install
.
Ngoài việc sử dụng gem pg
, chúng ta còn phải config các biến database của Heroku, và đảm bảo file config/database.yml
sử dụng adapter postgresql:
# config/database.yml
production:
<<: *default
adapter: postgresql
encoding: unicode
database: myapp_production
username: myapp
password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
Tạo app Heroku
Phải chắc chắn bạn đang ở trong folder có chứa Rails app, sau đó tạo app Heroku, tên bạn chọn phải chưa từng được sử dụng trên Heroku.
heroku create todo-pic-pjbelo
Sửa Credentials
Chạy lệnh sau để tạo biến môi trường RAILS_MASTER_KEY
với nội dung trong config/master.key
cho Heroku: heroku config:set RAILS_MASTER_KEY="$(< config/master.key)"
Thêm config Google Credentials vào Heroku: heroku config:set GOOGLE_APPLICATION_CREDENTIALS="$(< config/secrets/todo-pic.json)"
.
Bạn có thể kiểm tra biến môi trường ở Heroku bằng lệnh: heroku config
.
Sử dụng Rails Credentials
Nếu bạn không hứng thú với việc sử dụng Rails Credentials, bạn có thể chuyển thẳng sang phần sau là "Deploy App Heroku với Git".
Sử dụng Rails Credentials bạn sẽ không phải lo lắng về file key trên server production vì nó sẽ bị mã hóa, và bạn cũng không phải lo đến việc setting biến môi trường. Mở config/todo-pic.json
và copy tất cả nội dung.
Sửa rails credentials: rails credentials:edit
.
Thêm tên cho hash là gcs_todo_pic:
và dán toàn bộ nội dụng của file json vào. Đây là cách để 1 cái hash vào rails credentials. Sau đó lưu lại.
Bạn có thể kiểm tra bằng cách chạy:
rails console
puts Rails.application.credentials.gcs_todo_pic
Tiếp theo, sửa config storage.yml
:
# config/storage.yml
...
google:
service: GCS
project: todo-pic
credentials: <%= Rails.application.credentials.gcs_todo_pic.to_json %>
bucket: todo-pic-pjbelo
...
Phương thức to_json
sẽ convert định dạng từ hash thành json.
Deploy app Heroku với git
Nếu chưa commit thì nhớ add và commit các thay đổi vào, sau đó push lên Heroku:
git add
git commit -m 'init'
git push heroku master
Cuối cùng chạy migrate database: heroku run rake db:migrate
Chúc mừng!!!
Bạn đã deploy thành công Todo App với các tệp đính kèm trong Google Cloud. Kiểm tra tại: http://<your-app-name>.herokuapp.com.
Hy vọng bài viết có ích với bạn. Cảm ơn đã theo dõi!
All rights reserved