rake task, cron,whenever ①(rake task作成)

rake task, cron,wheneverの使い方を学んでいく。

rake taskを作成するときに必要なメソッド

rake task作成

$ rails g task hoge
success create lib/tasks/hoge.rake

作成されたファイルを編集する上で知っておきたいrakeタスクの書き方↓

namespace :hoge do
# タスクの説明 desc => description(説明)
  desc ""
  # task_name => タスクの名前
  task task_name: :environment do
    # 実行したい処理を記述する場所
  end
end

実際に編集していく。今回は、調子を確認してくれるrake taskを作成する

namespace :hoge do
# タスクの説明 desc => description(説明)
  desc "調子を確認してくれる"
  # howya_doin => タスクの名前
  task howya_doin: :environment do
    # 実行したい処理を記述する場所
		puts "How are you ?"
  end
end

これでrake taskが完成したので、作成されたかを確認する

$ rake -T

色々ズラーっとタスクが並んでいる中に、下記コードが追加されていたら作成に成功している。

rake hoge:howya_doin                   # How are you ?を表示するタスク

タスクを実行してみる。

rake hoge:howya_doin 

以下のような表示になれば成功。

How are you ?

cron

時間ごとにタスクが実行されるようにしてくれる優れもの

例えば、「XXというコマンドをXX時に実行する」というタスクを設定することができる。

whenever

ruby gemのうちの一つで、cronを使いやすくしてくれる優れもの。

wheneverをインストールした際に生成されるschedule.rbに、bundle exec whenever --update-crontab といったコマンドを記述することで、定期的にcronを実行してくれる。

rake taskの書き方応用

今回は、「もし下書きの投稿時間が現在時刻より過去のステータスだったら、ステータスを公開にかえる」というタスクにする。

(1)まず、「下書き状態の投稿」 を定義する。

Article.wait_publish

(2) 次に、(1)より前の投稿を探すメソッドを作る。(1)より前の投稿ということは、publish_atがTime.currentより前の投稿を探すことを意味しているので、コードに直すと下記の通りになる。

'published_at <?', Time.current

scopeを使ってモデルに定義すると、以下の通りになる。モデルに定義したスコープは別のコントローラで呼び出すことができるので、Fat Controller問題の解消に非常に役立つ方法。

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

さっき定義した「下書き状態の投稿」とこのscopeを組み合わせることで、「下書きの投稿時間が現在時刻より過去のステータス」の投稿を定義することができる。

Article.wait_publish.viewable

そして、最後にpublishを付け加えることで、

「下書きの投稿時間が現在時刻より過去のステータス」を「投稿する」(投稿というステータスに変える)

を実装することができる。

Article.wait_publish.viewable.publish

しかしこれだけだと、投稿数がひとつになってしまい、複数の現在時刻より過去の下書きを投稿することができない。

複数の項目を探して、それぞれの項目に対してメソッドを適用させたいときは、find_eachを使うと良い。

そして、探し出した項目それぞれを投稿状態に変えるために、&:published!を付け加える。

(3)
 find_each(&: published!)

(1), (2), (3) をつなげることで、

「もし下書きの投稿時間が現在時刻より過去のステータスだったら、ステータスを公開にかえる」というタスクを作成することができる。

Article.publish_wait.viewable.find_each(&:publish!)

そして 上記メソッドをlib/tasks/article_state.rakeに記載することで、rake taskを実行することができる。

$ rails g task article_state
success create lib/tasks/article_state.rake

lib/tasks/article_state.rake


namespace :article_state do
  desc 'もし下書きの投稿時間が現在時刻より過去のステータスだったら、ステータスを公開にかえる'
  task change_publish: :environment do
    Article.publish_wait.viewable.find_each(&:publish!)
  end
end

これで、rake taskをターミナル上で実行することができるようになった。

$ rake article_state:hange_publish
//Article.publish_wait.viewable.find_each(&:publish!)が実行される。

Rakeタスクの実装 - Qiita

ActiveModel::AttributeAssignment

rails learning rake task, cron, whenever