はじめに
Rakeタスクとは
Rakeとは、Rubyで人気のあるタスクランナーです。 タスクとは何か?
- データベースのバックアップを作成する
- テストの実行
- 統計の収集と報告
Rakeによってタスクへのアクセスを一元化することができます。 Rakeを使用すると、特定のパターンに一致し、最近変更されたファイルを探すことなどが容易になります。
cronとは
多くのUNIX系OSで標準的に利用される常駐プログラムの一種で、利用者の設定したスケジュールに従って指定されたプログラムを定期的に起動してくれるものです。 このcronに対して命令を行うには、crontab
を使います。
Rakeタスク
コマンドでlib/tasks
配下にrake
ファイルを作成します。
$ rails g task article_state
事前に公開日時が現在時刻から見て過去の記事を取得する為のscopeも作成しておきます。
scope :past_published, -> { where('published_at <= ?', Time.current) }
?
はプレースホルダと呼ばれ、第二引数で指定した値が置き換えられます。 つまり、Time.current
で取得された現在の時間が?
と置き換えれて、published_at
の値と<
で比較して検索します。
namespace :article_state do
desc '公開待ちの中で、公開日時が過去になっているものがあれば、ステータスを「公開」に変更されるようにする' # desc で処理の説明文を記入する
task change_to_be_published: :environment do # taskの名前を付ける。 environmentはDBへアクセスする場合に追記する。今回だとstateカラムの中身が変わるので必要。
Article.publish_wait.past_published.find_each(&:published!)
end
end
コードを紐解く
Article.publish_wait
このようにenum
のメソッドを使って、「公開待ち」であるデータを取得します。
find_each(&:published!)
find_each
は全データをメモリに展開して処理するのではなく、決まった単位(デフォルト1,000件)ごとにデータをメモリに展開しつつ処理するメソッドです。&:
はブロック内の省略記法です。以下のコードは同じ意味です。
Article.find_each(&:published!)
Article.find_each { |article| article.published! }
Rakeタスクの実行
Rakeタスクの一覧表示してみて、作成したタスクが登録されているか確認します。
> bundle exec rake --tasks
rake article_state:change_to_be_published # 公開待ちの中で、公開日時が過去になっているものがあれば、ステータスを「公開」に変更されるようにする
実行コマンド
$ bundle exec rake article_state:change_to_be_published
wheneverの導入
cronをrubyの記法で簡単に扱えるようにしたgemライブラリです。
GitHubの公式に沿って導入していきましょう。
gem 'whenever', require: false
require: false
: Railsの内部でwheneverを使うわけでは無いため、Railsの実行時に読み込まないようにするために付与しています。
$ bundle install
$ bundle exec wheneverize . # configディレクトリ配下にあるschedule.rbファイルを作成
schedule.rb
# Rails.rootを使用
require File.expand_path(File.dirname(__FILE__) + "/environment")
# cronを実行する環境変数(RAILS_ENVが指定されていないときはdevelopmentを使用)
rails_env = ENV['RAILS_ENV'] || :development
# cronの実行環境を指定(上記で作成した変数を指定)
set :environment, rails_env
# cronのログファイルの出力先指定
set :output, "#{Rails.root}/log/cron.log"
# パスを通すコマンド
job_type :rake, "source /Users/[ユーザー名]/.zshrc; export PATH=\"$HOME/.rbenv/bin:$PATH\"; eval \"$(rbenv init -)\"; cd :path && RAILS_ENV=:environment bundle exec rake :task :output"
# 一時間毎に実行する&タスク名の指定
every :hour do
rake 'article_state:change_to_be_published'
end
crontabを実行
crontabを使ってcronに対して命令をします。
$ bundle exec whenever --update-crontab # wheneverの設定更新
$ bundle exec whenever # 設定内容にエラーが無いか確認
$ crontab -l # 設定されているcronを確認
$ bundle exec whenever --clear-crontab # crontabの設定を削除
コメント