Rake task in Rails
Bài đăng này đã không được cập nhật trong 7 năm
Khái niệm
Rake là công cụ để quản lí các task trong rails, với mục đích gom nhóm các đoạn code ruby thường xuyên được sử dụng vào một task chung để sử dụng lại nhiều lần. Vd như các câu lệnh thường được chúng ta sử dụng nhiều như rake db:migrate
, rake db:create
, rake db:seed
, rake assets:precompile
.. Các câu lệnh này sẽ chạy các code ruby ở bên trong các Rakefile với namespace tương ứng.
Rails sẽ tự động lấy tất cả các rake file ở trong đường dẫn lib/tasks
và gom chúng vào danh sách các rake file hiện có trong rails app của chúng ta, và bên cạnh các rake task được định nghĩa sẵn của rails, chúng ta hoàn toàn có thể tùy ý tạo ra các rake task của riêng mình.
Tạo 1 Rakefile đơn giản
Để định nghĩa 1 rake file, chúng ta có thể dùng cú pháp:
rails g task [namespace] [task]
Sau khi thực hiện câu lệnh trên, trong thư mục lib/tasks
sẽ xuất hiện 1 file .rake
với tên file trùng với tên task.
Hoặc chúng ta có thể tạo file rake thủ công ở trong thư mục lib/tasks
, mình thường dùng cách này hơn.
Vd như chúng ta có Rakefile là user.rake
và định nghĩa 1 task là say_hi
:
namespace :user do
task :say_hi do
puts "hi"
end
end
Chạy thử Rakefile: rake user:say_hi
.
Tùy chọn dependency :environment
Khi định nghĩa 1 task, chúng ta cần thêm định nghĩa dependency :environment
để load Rails Enviroment cần thiết để có thể truy cập vào các model,..
Ở đây nếu như chúng ta chỉ định nghĩa các câu lệnh đơn giản như puts "hi" thì sẽ không cần định nghĩa dependency :environment
, nhưng khi chúng ta cần đụng chạm đến model User, vd như User.find(1)
hay User.create
, thì sẽ phải định nghĩa thêm:
namespace :user do
task :say_hi do
puts "hi"
end
task create: :environment do
User.create name: "A"
end
end
Dùng desc để thêm mô tả
Khi chúng ta định nghĩa nhiều tasks khác nhau trong cùng namespace, để rõ ràng hơn thì ta có thể thêm một vài mô tả trong file rake thông qua desc
:
namespace :user do
desc "this is user Rakefile"
...
Check Rake files list và default task
Xem toàn bộ danh sách rake hiện có trong app: rake -T
The default task: task mặc định khi chạy rake, khai báo qua cú pháp task default: [:name]
Invoking tasks
Có 1 kỹ thuật rất hay được sử dụng là Invoking task. Dùng để gọi task này ở trong task khác với cú pháp: Rake::Task["task_name"].invoke
Vd như ta định nghĩa 1 rake task để mỗi khi gọi đến thì sẽ reset lại db và seeding lại dữ liệu, điều này tương đương với việc gọi các task: db:drop
, db:create
, db:migrate
..
namespace :db do
desc "remake database data"
task remake_data: :environment do
%w[db:drop db:create db:migrate].each do |task|
Rake::Task[task].invoke
end
puts "You will be prompted to create data for project."
100.times do |n|
name = Faker::Name.name
email = "email-#{n+1}@framgia.com"
password = "password"
User.create! name: name, email: email, password: password,
password_confirmation: password
end
puts "The data was created successfully."
end
end
Và sau đó chúng ta chỉ việc gọi đến task đó khi cần remake lại db với lệnh: rake db:remake_data
Task Overriding
Rails cũng cho phép chúng ta định nghĩa lại 1 task mặc định, chẳng hạn như db:migrate
. Lưu ý ở đây là task mới mà chúng ta định nghĩa lại sẽ không override lại hoàn toàn mà chỉ đơn giản là thêm các dòng lệnh phía sau task gốc đó. Để định nghĩa lại 1 task, cần dùng cùng name:
namespace :db do
task migrate: :environment do
puts "I'm overriding db:migrate task."
end
end
Passing Argument
Chúng ta cũng có thể truyền tham số hoặc sử dụng biến ENV trong Rake task. Cách thứ nhất là chúng ta có thể truyến thẳng tham số vào task, vd:
namespace :calculate do
task :add, [:num1, :num] do |t, args|
puts args[:num1].to_i + args[:num].to_i
end
end
rồi gọi: rake calculate:add[1,2]
, kết quả in ra màn hình sẽ là 3.
Tuy nhiên với cách truyền trực tiếp như vậy thì với những người dùng zsh shell sẽ gặp lỗi ở công đoạn gọi rake:
zsh: no matches found: calculate:add[1,2]
Nguyên nhân là vì chúng ta chưa "escape" dấu ngoặc vuông [
, cách xử lí là viết lại lệnh gọi rake như sau: rake calculate:add\[1,2\]
, kết quả sẽ in ra ngon lành.
Nhìn không được đẹp mắt lắm, may mà chúng ta còn 1 số cách khác trọn vẹn cả 2, chẳng hạn như sử dụng biến môi trường ENV
:
namespace :calculate do
task :add do
puts ENV['NUM1'].to_i + ENV['NUM2'].to_i
end
end
rồi gọi: rake calculate:add NUM1=1 NUM2=2
Tuy nhiên ở đây ngoại trừ việc không cần thêm kí tự escape rắc rối như cách đầu, cú pháp được giữ nguyên định dạng, thì đối với trường hợp này việc set giá trị cho các biến ENV thường là không cần thiết.
Còn 1 vài cách khác để truyền biến vào trong task, các bạn có thể tham khảo thêm ở đây.
Lời kết
Mình xin đóng góp chút kiến thức nhỏ về Rake task Rails để chia sẻ với mọi người. Bài viết còn nhiều thiếu sót, mong được mọi người góp ý, cảm ơn vì đã dành thời gian đọc bài viết của mình.
All rights reserved