Sha256: 764212ac0ec01a873270e9586b1c5a545abcbe407a067c4b0a953d44a0a2ac20

Contents?: true

Size: 1.69 KB

Versions: 1

Compression:

Stored size: 1.69 KB

Contents

# frozen_string_literal: true

require 'uniqable/version'

# Generates uniq, random token for ActiveRecord model's fields
module Uniqable
  def self.included(base)
    base.extend ClassMethods
  end

  # Methods going to be AR model's methods
  module ClassMethods
    # Uniqable fields and options declaration
    # @example:
    #   uniqable :uid, :slug, to_param: :uid
    # rubocop:disable Metrics/MethodLength
    def uniqable(*fields, to_param: nil)
      fields = [:uid] if fields.blank?
      fields.each do |name|
        before_create { |record| record.uniqable_uid(name) }
      end
      define_singleton_method :uniqable_fields do
        fields
      end

      return if to_param.blank? # :to_param option

      define_method :to_param do
        public_send(to_param)
      end
    end
    # rubocop:enable Metrics/MethodLength

    # @return [self]
    def where_uniqable(uid)
      where(
        uniqable_fields.map { |r| "#{table_name}.#{r} = :uid" }.join(' OR '),
        uid: uid
      )
    end

    # Find record by one of the uniq field
    # usage @example:
    #   uniqable :uid, :slug
    #   ...
    #   MyModel.find_uniqable params[:uid] # can be uid or slug column
    # @return [self]
    def find_uniqable(uid)
      where_uniqable(uid).take
    end

    # Same as method above just raise exception if nothing is there
    # @return [self]
    def find_uniqable!(uid)
      where_uniqable(uid).take!
    end
  end

  # Generate and set random and uniq field
  # @TODO: split into 2 actions generate and set
  def uniqable_uid(field)
    loop do
      uniq_code = SecureRandom.hex(8)
      send("#{field}=", uniq_code)
      break unless self.class.where(field => uniq_code).exists?
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
uniqable-0.3.2 lib/uniqable.rb