はじめに
Railsアプリでデータベースにメールを送りたい日を保存、保存された日にメールを送る方法について初心者なりにまとめました
動作環境
Ruby 3.0.1
Rails 6.1.6
whenever 1.0.0
実装の流れ
作る順番は以下の通りです。
- ActionMailerで実際にメールを送る機能を作って実際に送れるか試す(こちらを参考に)
- wheneverを導入(こちらを参考に)
- 1で作ったメール送信機能を実行するメソッドを作る
- wheneverで3を実行するように書き換える
本記事では3・4の工程についてまとめています
下のスクリーンショットが最終的な実装です
1番上の行でメソッドを実行する時間を指定(毎日3.30)
2行目の「runner “中身”」の「中身」が定期的に実行される機能となっています

この図だとStockpileクラスの.notice_on_checkメソッドが実行されます
つまりnotice_on_checkの定義はStockpileモデルにしています
(Stockpileテーブルにdatetime型を保持してあるのでStockpileモデルに定義しました)
cronで実行するメソッドの定義

上のスクリーンショットはcronで実行するnotice_on_checkのメソッド定義です
場所はapp/models/stockpile.rb。つまりモデルの.rbとなっています。
IF文でメールを送る条件が正ならStockMailerが実行されるよう定義しています(上の図の3行目が条件、4行目がメールを送る動作)
each文について
Stockpileに入っている時間のレコード全部を調べたいのでeachメソッドで取り出して実行しています。
条件について詳しく
条件文に使っている時間について
時刻を戻り値として得るのに
Time.now
を利用しています。

(railscで確かめると日付と時間が出力)
しかし日付だけで比べたいので
Time.now.to_date
を利用します。

こちらだと日付だけで比較演算子で比べることができて時間を考慮せずに比べられるためです。
Railsのデータベース内にデータ型:datetimeで保存してあるレコードはRubyのタイムクラスの戻り値が返ってくるので上記のコードと比較演算子で比較できます。
If Stockpile.notice_on.to_date < Time.now.to_date
hogehoge
else
bugbug
end
この例のように「stockpiles」テーブルの「notice_on」というカラムにdatetime型でデータが保存されているとき、「notice_on」はdatetime型なので「Time.now」の戻り値である現在時刻と比べることができます。
保存している日にちと現時刻を比べて
- 現時刻の方が遅ければ「hogehoge」
- 現時刻の方が早ければ「bugbug」
を実行するといった使い方ができます。