1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails4 delayed_jobでイベント管理機能

Last updated at Posted at 2016-08-21

動機

Delayed_jobは処理に時間が掛かるようなタスクをバックグラウンドで非同期処理を実現するGemです。
delayed_jobをつかった簡単な使い方はいろいろなところで見かけますが、ジョブをハンドルして、特に削除を好きなタイミングで行う方法がわからず調べるのに苦労したのでまとめておきます。

delayed_jobの設定方法などはインストールなどの情報はこちら
【Rails 4】delayed_jobを使う

今回作りたかったのは以下の機能です

  • connpassのようなイベントサイトの簡易版として、イベント登録、参加者募集し、日程の管理などもできるようなサービス
  • イベントは下書き、公開、終了という状態を持っていてイベントがおわると自動的に終了状態になる-①
  • このサービスはイベントの参加者に実施日の24時間前にリマインダーを送信する。②
  • 25時間前まではイベントの開催時間、を変更可能でリマインダー開催、終了時刻を設定しなおす。

model設計

Event : イベント内容、開始時刻、終了時刻を保持
EventJob : イベントのリマインダー、終了状態遷移遷移処理、delayed_jobのモデルである__Delayed::Backend::ActiveRecord::Job__へのハンドル(idを保持する)


  # イベント
  create_table "events", force: :cascade do |t|
    t.string   "content"
    t.datetime "start_datetime"
    t.datetime "end_datetime"
    t.string   "state"
    t.string   "title"
  end

  # ジョブ
  create_table "event_jobs", force: :cascade do |t|
    t.integer  "job_type",   null: false
    t.integer  "event_id",   null: false
    t.integer  "job_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end


実装

  • __EventJob__モデル
# イベントに関するジョブを削除できるようにハンドルを保持するため、モデルとして扱う
class EventJob < ActiveRecord::Base

  belongs_to :event
  
  # reminder リマインダージョブ
  # finish 終了 
  enum job_type: { reminder: 0, finish: 1 }
  scope :reminder, ->() {find_by_job_type(0)}
  scope :finish, ->() {find_by_job_type(1)}

  before_destroy :delete_job

  # ジョブを設定する
  def setup!
    if reminder? 
      update!(job_id: delay(run_at: event.start_datetime - 1.day).exec_remider.id)
    elsif finish?
      update!(job_id: delay(run_at: event.end_datetime).exec_finish.id)
    else
      logger.info('unknown_jobtype')
    end
  end

  # ジョブを再設定する
  # 時刻変更のため
  def reset!
    delete_job
    setup!
  end

  private

  def exec_remider
    # リマインダー送信セットアップ
    # ここでメールを送る処理を実装
  end

  def exec_finish
    # イベント終了
    # ここはAASM というステートマシンGEMを利用して状態を変更
    event.finish!
  end

  def delete_job
    Delayed::Backend::ActiveRecord::Job.find_by_id(job_id).try(:destroy)
  end
end

ここのコードのポイントは__EventJob__クラスのメソッドをdelayつきで呼ぶと、戻り値がDelayed::Backend::ActiveRecord::Jobtoとなるのでここでハンドル(id)を取得することができます!


delay(run_at: event.start_datetime - 1.day).exec_remider
=> #<Delayed::Backend::ActiveRecord::Job:0x007fa352365b58
  •  呼び出す側
  def setup_finish
    # 終了状態にする
    logger.info('終了状態にするジョブをセットします!')
    EventJob.create(event_id: id, job_type: 'finish').setup!
  end

  def setup_reminder
    # リマインダーをセットアップする
    logger.info('リマインダーセットします!')
    EventJob.create(event_id: id, job_type: 'reminder').setup!
  end

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?