Rails

Rakeタスクをつくる

More than 5 years have passed since last update.

定期的なメンテナンスをRakeタスクとして登録して呼び出したいと考えました。

Rakeタスクの作り方を調べたのでメモ。

シナリオは、メール認証が一週間以上されないユーザーのレコードを削除するです。

$ rails g task inactive_user #=> inactive_userが名前

#=> rake inactive_user:xxx のように使うので名前に気をつけて


lib/tasks/destroy_inactive_user.rake

# encoding: utf-8

namespace :inactive_user do
desc "Users中confirm_atから1週間が経過していれば削除" #=> 説明

# $ rake inactive_user:destroy_unconfirmed のように使う
# :environmentは超大事。ないとモデルにアクセスできない

task :destroy_unconfirmed => :environment do
User.all.each do |user|
user.destroy if (Time.now > user.confirm_at + 1.weeks.ago)
end
end
end


これでOK

タスクが登録されているか確認してみる

$ rake -vT

# 略
rake inactive_user:destroy_suspended # Users中suspended_atから3ヶ月経過していていれば削除
rake inactive_user:destroy_unconfirmed # Users中confirm_atから1週間が経過していれば削除
rake inactive_user:list_suspended # Users中suspended_atから3ヶ月経過していていれば表示
rake inactive_user:list_unconfirmed # Users中confirm_atから1週間が経過していれば表示

ちゃんと入ってますね。

実際に動かしてみる、、、前にいきなり削除すると怖いので、


lib/tasks/destroy_inactive_user.rake

# encoding: utf-8

namespace :inactive_user do
desc "Users中confirm_atから1週間が経過していれば削除"
task :destroy_unconfirmed => :environment do
User.all.each do |user|
puts user.to_yaml if (Time.now > user.confirm_at + 1.weeks.ago)
end
end
end


こう変えましょう。

先にデータベースの下ごしらえをします。

モデルは何となく想像してください。

$ rails c

>> User.create({:name => "new", :email =>"a@example.com", :confirmed => false, :confirm_at => Time.now}) #=> 成功すること

>> User.create({:name => "old", :email =>"b@example.com", :confirmed => false, :confirm_at => 1.weeks.ago})  #=> 成功すること

実行します。

$ rake inactive_user:destroy_unconfirmed

--- !ruby/object:User
attributes:
id: 3
name: old
email: b@example.com
created_at: 2012-09-18 10:42:32.000000000 Z
updated_at: 2012-09-18 10:42:32.000000000 Z
confirmed: false
confirm_at: 2012-09-11 10:42:32.000000000 Z

ちゃんと捕捉できました。

では削除用スクリプトに書き直して、、、ログも残しておきたいですよね?


lib/tasks/destroy_inactive_user.rake

# encoding: utf-8

namespace :inactive_user do
desc "Users中confirm_atから1週間が経過していれば削除"
task :destroy_unconfirmed => :environment do
User.all.each do |user|
logger = Logger.new('log/inactive_user.log')
logger.info "#{Time.now} -- destroy_unconfirmed_inactive_user -- #{user.to_yaml}"
user.destroy if (Time.now > user.confirm_at + 1.weeks.ago)
end
end
end


こうしました。

実行します。

$ rake inactive_user:destroy_unconfirmed

Process finished with exit code 0


log/inactive_user.log

# Logfile created on 2012-09-18 19:58:37 +0900 by logger.rb/31641

2012-09-18 19:58:37 +0900 -- destroy_unconfirmed_inactive_user -- --- !ruby/object:User
attributes:
id:
3
name: old
email: b@example.com
created_at: 2012-09-18 10:42:32.000000000 Z
updated_at: 2012-09-18 10:42:32.000000000 Z
confirmed: false
confirm_at: 2012-09-11 10:42:32.000000000 Z


ログもとれました。

以上で機能を達成できましたが、もっと良い方法だったり問題点があれば教えてください。

具体的なシナリオを言及した投稿がもっとたくさんあるといいですね。