[Rails] Implementation of coupon function (with automatic deletion function using batch processing)

Target

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

Development environment

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

Premise

The following has been implemented.

Slim introductionIntroduction of Bootstrap3 -Login function implementationImplementation of posting function

Implementation

1. Add column

Terminal


$ 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:Added "true"
      t.integer :limit

      t.timestamps
    end
  end
end

Terminal


$ rails db:migrate

2. Edit the model

user.rb


#Postscript
has_many :coupons, dependent: :destroy

coupon.rb


class Coupon < ApplicationRecord
  belongs_to :user

  enum is_valid: { 'Effectiveness': true, 'Invalid': 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 == 'Effectiveness'
        coupon.is_valid = 'Invalid'
        coupon.save
      end
    end
  end
end

[Explanation]

① Manage the coupon status with enum.

enum is_valid: { 'Effectiveness': true, 'Invalid': false }

(2) Define a method to create a coupon.

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

③ Define a method to delete the coupon.

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 == 'Effectiveness'
      coupon.is_valid = 'Invalid'
      coupon.save
    end
  end
end

** ◎ If 24 hours have passed since the coupon was created and the coupon status is valid, change it to invalid and save it. ** **

if coupon.created_at + coupon.limit.minutes < time && coupon.is_valid == 'Effectiveness'
  coupon.is_valid = 'Invalid'
  coupon.save
end

3. Create / edit coupons_controller.rb

Terminal


$ rails g controller coupons index

coupons_controller.rb


class CouponsController < ApplicationController
  def index
    @coupons = Coupon.where(user_id: current_user.id, is_valid: 'Effectiveness') 
  end
end

4. Edit books_controller.rb

This time, we will implement a coupon to be issued when the book is posted successfully.

books_controller.rb


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

5. Change the date and time settings

① Edit ʻapplication.rb`.

application.rb


module Bookers2Debug
  class Application < Rails::Application
    config.load_defaults 5.2
    config.time_zone = 'Tokyo' #Postscript
  end
end

(2) Create / edit a file to set the date and time format

Terminal


$ touch config/initializers/time_formats.rb

time_formats.rb


Time::DATE_FORMATS[:datetime_jp] = '%Y/%m/%d/%H:%M'

6. Edit the view

slim:coupons/index.html.slim


.row
  .col-xs-3

  .col-xs-6
    table.table
      thead
        tr
          th
            |Coupon number
          th
            |title

      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

[Explanation]

(1) Display one day after the coupon creation date and time in the format set in 5.

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

7. Implementation of automatic deletion function

① Introduce Gem

Gemfile


#Postscript
gem 'whenever', require: false

Terminal


$ bundle

② Create and edit " schedule.rb "

Terminal


$ bundle exec wheneverize .

config/schedule.rb


env :PATH, ENV['PATH'] #Specify a relative path from an absolute path
set :output, 'log/cron.log' #Set the log output destination file
set :environment, :development #Set environment

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

4. Reflect cron

Terminal


$ bundle exec whenever --update-crontab

Commands often used in batch processing

crontab -e ➡︎ Edit cron on the terminal

$ bundle exec whenever ➡︎ Check cron settings

$ bundle exec whenever --update-crontab ➡︎ Reflect cron

$ bundle exec whenever --clear-crontab ➡︎ Remove cron

Recommended Posts

[Rails] Implementation of coupon function (with automatic deletion function using batch processing)
[Rails] Implementation of multi-layer category function using ancestry "Preparation"
[Rails] Implementation of multi-layer category function using ancestry "seed"
[Rails] Implementation of tutorial function
[Rails] Implementation of like function
[Rails] Implementation of tag function using acts-as-taggable-on and tag input completion function using tag-it
Implementation of user authentication function using devise (3)
[Ruby on rails] Implementation of like function
Resolved strange HTML display by reviewing Rails dynamic processing
[Rails] I tried to implement batch processing with Rake task
Learn regular expressions little by little ①
Unit catcher made by Processing
[Docker] Use whenever with Docker + Rails
Rails singular resource routing by resource
[Rails] Implementation of coupon function (with automatic deletion function using batch processing)
Ruby on Rails Email automatic sending function implementation
[Rails] Implementation of PV number ranking using impressionist
[Rails] Implementation of image slide show using Bootstrap 3
Using PAY.JP API with Rails ~ Implementation Preparation ~ (payjp.js v2)
Implementation of pagination function
Control the processing flow of Spring Batch with JavaConfig.
Rails CRUD function implementation ① (new addition, deletion this time)
[Rails] Implement event end function (logical deletion) using paranoia (gem)
[Rails] I tried to implement batch processing with Rake task
Implementation of category pull-down function
Read the implementation of Rails 6 multi-DB automatic switching (ActiveRecord :: Middleware :: DatabaseSelector)
Implementation of validation using regular expressions
[Rails] Implementation of many-to-many category functions
[Rails] gem ancestry category function implementation
[Ruby on Rails] Comment function implementation
[Kotlin] Example of processing using Enum
[Rails] Comment function implementation procedure memo
Docker [Batch deletion of <none> tags]
Implementation of like function in Java
Introduction of Sudoku answer application "Sudoku automatic answer" (Android version) and its implementation function
Signature verification implementation (Rails) for detecting tampering with request parameters using JWT