42 lines
1.0 KiB
Ruby
42 lines
1.0 KiB
Ruby
class Account::JoinCode < ApplicationRecord
|
|
CODE_LENGTH = 12
|
|
|
|
scope :active, -> { where("usage_count < usage_limit") }
|
|
|
|
before_validation :generate_code, on: :create, if: -> { code.blank? }
|
|
|
|
validates :code, presence: true, uniqueness: true
|
|
validates :usage_limit, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
|
validates :usage_count, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
|
|
|
class << self
|
|
def redeem(code)
|
|
find_by(code: code)&.tap do |join_code|
|
|
if join_code.active?
|
|
join_code.increment!(:usage_count)
|
|
end
|
|
end
|
|
end
|
|
|
|
def active?(code)
|
|
active.exists?(code: code)
|
|
end
|
|
end
|
|
|
|
def active?
|
|
usage_count < usage_limit
|
|
end
|
|
|
|
def reset
|
|
update!(code: generate_code, usage_count: 0)
|
|
end
|
|
|
|
private
|
|
def generate_code
|
|
self.code = loop do
|
|
candidate = SecureRandom.base58(CODE_LENGTH).scan(/.{4}/).join("-")
|
|
break candidate unless self.class.exists?(code: candidate)
|
|
end
|
|
end
|
|
end
|