LoginSignup
6
9

More than 3 years have passed since last update.

【Rails】クーポン機能の実装(バッチ処理を用いた自動削除機能付き)

Posted at

目標

ezgif.com-video-to-gif (1).gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
Bootstrap3導入
ログイン機能実装
投稿機能実装

実装

1.カラムを追加

ターミナル
$ rails g model Coupon user_id:integer is_valid:boolean limit:integer
~__create_coupons.rb
class CreateCoupons < ActiveRecord::Migration[5.2]
  def change
    create_table :coupons do |t|
      t.integer :user_id
      t.boolean :is_valid, default: true # 「default: true」を追記
      t.integer :limit

      t.timestamps
    end
  end
end
ターミナル
$ rails db:migrate

2.モデルを編集

user.rb
# 追記
has_many :coupons, dependent: :destroy
coupon.rb
class Coupon < ApplicationRecord
  belongs_to :user

  enum is_valid: { '有効': true, '無効': false }

  def self.coupon_create(user)
    coupon = Coupon.new(user_id: user.id, limit: 1)
    coupon.save
  end

  def self.coupon_destroy
    time = Time.now
    coupons = Coupon.all
    coupons.each do |coupon|
      if coupon.created_at + coupon.limit.days < time && coupon.is_valid == '有効'
        coupon.is_valid = '無効'
        coupon.save
      end
    end
  end
end

【解説】

① クーポンの状態をenumで管理する。

enum is_valid: { '有効': true, '無効': false }

② クーポンを作成するメソッドを定義する。

def self.coupon_create(user)
  coupon = Coupon.new(user_id: user.id, limit: 1)
  coupon.save
end

③ クーポンを削除するメソッドを定義する。

def self.coupon_destroy
  time = Time.now
  coupons = Coupon.all
  coupons.each do |coupon|
    if coupon.created_at + coupon.limit.days < time && coupon.is_valid == '有効'
      coupon.is_valid = '無効'
      coupon.save
    end
  end
end

◎ クーポンを作成してから24時間経過かつ、クーポンの状態が有効の場合は、無効に変更して保存する。

if coupon.created_at + coupon.limit.minutes < time && coupon.is_valid == '有効'
  coupon.is_valid = '無効'
  coupon.save
end

3.coupons_controller.rbを作成・編集

ターミナル
$ rails g controller coupons index
coupons_controller.rb
class CouponsController < ApplicationController
  def index
    @coupons = Coupon.where(user_id: current_user.id, is_valid: '有効') 
  end
end

4.books_controller.rbを編集

今回は本を投稿成功した場合に、クーポンを発行するように実装します。

books_controller.rb
def create
  @book = Book.new(book_params)
  @book.user_id = current_user.id
  if @book.save
    Coupon.coupon_create(current_user) # 追記
    redirect_to books_path
  else
    @books = Book.all
    render 'index'
  end
end

5.日時設定を変更

application.rbを編集する。

application.rb
module Bookers2Debug
  class Application < Rails::Application
    config.load_defaults 5.2
    config.time_zone = 'Tokyo' # 追記
  end
end

②日時のフォーマットを設定するファイルを作成・編集

ターミナル
$ touch config/initializers/time_formats.rb
time_formats.rb
Time::DATE_FORMATS[:datetime_jp] = '%Y/%m/%d/%H:%M'

6.ビューを編集

coupons/index.html.slim
.row
  .col-xs-3

  .col-xs-6
    table.table
      thead
        tr
          th
            | クーポン番号
          th
            | タイトル

      tbody
        - @coupons.each.with_index(1) do |coupon, index|
          tr
            td
              = index
            td
              - limit = coupon.created_at + coupon.limit.minutes
              = limit.to_s(:datetime_jp)

  .col-xs-3

【解説】

① クーポン作成日時の1日後を、5で設定したフォーマットで表示する。

- limit = coupon.created_at + coupon.limit.minutes
= limit.to_s(:datetime_jp)

7.自動削除機能の実装

① Gemを導入

Gemfile
# 追記
gem 'whenever', require: false
ターミナル
$ bundle

「schedule.rb」を作成・編集

ターミナル
$ bundle exec wheneverize .
config/schedule.rb
env :PATH, ENV['PATH'] # 絶対パスから相対パス指定
set :output, 'log/cron.log' # ログの出力先ファイルを設定
set :environment, :development # 環境を設定

every 1.minute do
  runner 'Coupon.coupon_destroy'
end

4.cronを反映

ターミナル
$ bundle exec whenever --update-crontab

バッチ処理でよく使うコマンド

crontab -e ➡︎ cronをターミナル上で編集

$ bundle exec whenever ➡︎ cronの設定を確認

$ bundle exec whenever --update-crontab ➡︎ cronを反映

$ bundle exec whenever --clear-crontab ➡︎ cronを削除

6
9
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
6
9