はじめに
本記事は自分自身の備忘録として書いていますが、同じような実装を考えている方々の参考になればと思います。
また、私と同様、プログラミングを初めたばかりの方々向けに投稿していますので、できるかぎりシンプルに記載していきます!
※ runner以外のコマンドや crontab などの説明は本記事では割愛しています。
開発環境
Ruby : 2.5.1
Rails : 5.0.7.2
Whenever : 1.0.0
実現したいこと
ネットショップなどを想定して、出品中の商品全品を定期的に値下げしたい。
また、処理を自動で行いたい。
具体的に以下の1, 2を繰り返し実行したい。
- 毎週末(土日)に全商品が10%オフになる
- 毎月曜日に元値に戻す
実装の流れ
よくある、「週末は10%オフのセール!」みたいなやつを Whenever を使用して実装していきます。
前置き
まず、定期実行をする際に重宝するのが Whenever という Gem です。
タスクに登録して好きなタイミングで自動実行してくれます。
学習コストが低く、私のような初心者でも取っつきやすいのが特徴です!
Github: javan/whenever
本題
[1] タスクを作成する
必要なメソッドを備えた class や module が何処かにあれば良いと思いますが、今回は分かりやすく「lib/tasks」直下に「lib/tasks/product_task」ファイルを作成します。
また、このファイルに実行したい処理を記述します。
(lib/tasks/product_task.rb)
class Tasks::Product_task
# 10%オフを実行するメソッド
def self.set_time_sale
Product.update_all("price = price * 0.9")
end
# 10%オンを実行するメソッド
def self.end_time_sale
Product.update_all("price = price / 0.9")
end
end
[2] タスクのパスをオートロードにする
Whenever から「lib/tasks」を呼び出せるようにパスを通す必要があります。
開発環境では config.autoload_paths 、本番環境では config.eager_load_paths が必要となります。
(config/application.rb)
module [アプリ名]
class Application < Rails::Application
(省略)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
config.eager_load_paths += Dir["#{config.root}/lib/**/"]
end
end
[3] 手動で確認
ここで一度、設定ができているか確認をします。
(ターミナル)
$ bundle exec rails runner Tasks::Product_task.set_time_sale
動作問題なければタスクの設定は完了です!
[4] Whenever の導入
Gemfile に記述し、bundle install します。
(Gemfile)
gem 'whenever', :require => false
[5] Whenever の設定ファイルを作成
下記コマンドを打つと、「config/schedule.rb」が作成されます。
これがcrontabの元になり、「○曜日にxxを実行」みたいな処理をこのファイルに記述していきます。
(ターミナル)
$ bundle exec wheneverize
[6] schedule.rbの編集
先ほど作ったタスクを登録する為、以下のように記述します。
(config/schedule.rb)
require File.expand_path(File.dirname(__FILE__) + "/environment")
rails_env = Rails.env.to_sym
rails_root = Rails.root.to_s
# デフォルトは本番環境になる為、明示的に開発環境を指定する
set :environment, rails_env
set :output, "#{rails_root}/log/cron.log"
# 毎週末にタスクで定義した set_time_sale を実行する
every :weekend do
runner 'Tasks::Product_task.set_time_sale'
end
# 毎週月曜日にタスクで定義した end_time_sale を実行する
every :monday do
runner 'Tasks::Product_task.end_time_sale'
end
[7] crontabへ反映させる
(ターミナル)
$ bundle exec wheneverize
[write] crontab file updated がターミナル上に出てくれば登録完了です!
お疲れさまでした!
補足
今回の実装コードはあくまで、開発環境でのみ機能する仕様です。
本番環境は別途対応が必要になりますので、以下の記事などを参考にしてください。
一つ注意点としては、Herokuはサポートされていないみたいです。
もしHerokuで定期実行したいタスクがあるのなら「Heroku Scheduler」を活用しましょう。
また、本実装はこのままでは問題点があります。。
月曜日に出品した商品は10%オンした状態になる為、修正が必要です。
内容については、実現したいことに合わせて書き換えてご活用ください。