Rakeタスク Cron Whenever 一時間ごとに表示させる

Rakeタスク

まずRakeとは、rubyで処理内容を定義できるビルドツールです。 そしてこのRakeが実行する処理内容を「Rakeタスク」と呼び、定義する場所を「Rakefile」と呼びます。 whenneverと組み合わせることにより、自由なタイミングで処理を走らせることができます。


タスク

タスクとは、テストの実行やデータベースの更新などのタスクを実行してくれます。Rakeなしでこのような小さなタスクを実行しようと思うと、違うファイルを行き来してしまい、コードが散らかります。


cron

「クロン」または「クーロン」と呼ばれ、「○時になったら○○のコマンドを実行」などといった具合に、定期的にコマンドを実行するためにメモリ場で常に命令を待機しているプロセス(=デーモンプロセス)となります。


ファイル作成

lib/tasks以下ディレクトリにrakeファイルを作ります。

rails g task _article_state

※間違いで_article_stateと入力してしまいました。正しくはarticle_state
rakeタスクに実装していく。

_article_state.rake

 namespace :article_state do
   desc '公開待ちの中で、公開日時が過去のもの:ステータスを「公開」に変更する'
   task update_article_state: :environment do
     Article.publish_wait.past_published.find_each(&:published!)
   end
 end

task_nameがタスクの名前になります。どういう処理を行うタスクなのか分かりやすい名前をつけてあげると、後々タスクが増えた時にも混乱しなくて済みます。 DBとのやり取りがある処理の場合「:environment」を記載する必要がある。 Articleから「公開待ち」の状態で公開日時が現在〜過去のものを取ってきてから、find_eachでループさせます。 必要なデータだけ先に抽出してから繰り返し処理をしています。 (&:メソッド名)でpublished!を実行しています。 Rubyチェリー本P98に詳細の説明あり。


公開日時が現在〜過去の記事を取得するscopeを準備 article.rb

scope :past_published, -> { published.where('published_at <= ?', Time.current) }


Rakeタスクの実行

Rakeタスクの一覧を表示して登録されているか確認します。

以下のコマンドを入力することで、Rakeタスクの一覧を表示してくれます。以下は同じ出力結果になります。

bundle exec rake --tasks
bundle exec rake -T

Image from Gyazo

bundle exec rake _article_status:manage_status


Wheneverの導入

Wheneverはcron jobを実行してくれます。つまり、cronをruby文法で実行してくれるライブラリーです。 本来は「○○時になったら○○を実行」するcronというプロセスを自前で用意する必要があるのですが、wheneverを使えばcronに対して命令を行うcrontabに記述する内容をruby言語で書けるようになります。 これによりRakeタスクを1時間ごとに走らせるように設定することが可能です。

gem 'whenever', require: false
% bundle exec wheneverize .

schedule.rbファイル内にcron処理の設定を書き込む。 schedule.rb

 # Rails.rootを使用するために必要
 require File.expand_path(File.dirname(__FILE__) + '/environment')
 # cronを実行する環境変数
 rails_env = ENV['RAILS_ENV'] || :development
 # cronを実行する環境変数をセット
 set :environment, rails_env
 # cronのログの吐き出し場所
 set :output, "#{Rails.root}/log/cron.log"
 # 1時間ごとにrakeタスクを実行
 every :hour do
   rake 'article_state:update_article_state'
 end

公開日時を1時間ごとにしか設定できないようにする。 app/assets/javascripts/admin.js

format: 'YYYY-MM-DD HH:00'


Cronをアップデートする

$ bundle exec whenever --update-crontab

crontab -lで現在設定されているタスクの一覧が表示されます。