やりたいこと
ポートフォリオとしてイベント投稿アプリを作成中イベントの開催日が過ぎたイベントの扱いをどうしようかと調べていたら論理削除の存在を知ったのでイベントを論理削除してイベントを閉鎖する機能を自作した。
機能要件
実装の前に今回の機能要件をまとめると、
① イベントの期日が過ぎたイベントを論理削除する
具体的には、
- イベントカラムにbooleanを持たせる
- 開催日が過ぎたイベントのbooleanの状態でViewの表示を変更する
② 論理削除はイベント期日が過ぎたら自動で実行
具体的には、
- イベント開催日が過ぎたらbooleanを変更するメソッドを定義
- そのメソッドをrakeタスクに登録
- rakeタスクを定期実行する
実装
それでは実装開始!
① イベントの期日が過ぎたイベントを論理削除する
イベントカラムにbooleanを持たせる
命名は今回はstatusとしてデフォルトをfalseに設定する
コンソール
$ rails g migration AddStatusToEvents status:boolean
class AddStatusToEvents < ActiveRecord::Migration[6.1]
def change
add_column :events, :status, :boolean, default: false
end
end
コンソール
$ rails db:migrate
開催日が過ぎたイベントのbooleanの状態でViewの表示を変更する
やることは簡単
viewの表示を条件分岐するだけ
view
- if @event.status?
.btn.btn-danger 終了
- else
.btn.btn-primary 参加する
画面で表すとこんな感じ
これでイベントの開催日が過ぎたことが一目瞭然!
② 論理削除はイベント期日が過ぎたら自動で実行
イベント開催日が過ぎたらbooleanを変更するメソッドを定義
ここがなんだかんだ一番悩んだ場所
日付の処理をどうするか色々調べた結果以下のような形に
railsはDate.todayで今日の日にちが取れることを初めて知った。
Event.where('start_time < ?', Date.today).where(status: false).update_all(status: true)
そのメソッドをrakeタスクに登録
あとは定期実行するためにrakeタスクに登録
ターミナル
$ rails g task close_event
lib/tasks/close_event.rake
namespace :close_event do
desc "イベント開催日が過ぎたらイベントをcloseする"
task close_event: :environment do
Event.where('start_time < ?', Date.today).where(status: false).update(status: true)
end
end
一応ここで動作確認
ターミナル
$ rake close_event:close_event
rakeタスクを定期実行する
定期実行にはwheneverを使う
Gemfile
gem 'whenever', require: false
ターミナル
$ bundle install
設定ファイルをインストール
ターミナル
$ bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized!
設定を書いてrakeタスクが毎朝6時に実行されるようにセット
config/schedule.rb
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"
# 時間指定
every 1.day, at: '6am' do
rake 'close_event:close_event'
end
cronを更新して完成
ターミナル
$ bundle exec whenever --update-crontab
まとめ
実装する前に機能要件と機能実装の流れを具体的にすることでスムーズに実装することができた。
機能を自作するのは大変だったがとても楽しかった!