module Enummer::Extension

Public Instance Methods

enummer(values) click to toggle source

@param [Hash] values The attribute name to options mapping for an multi-option enum @option values [Boolean|String] :_prefix The prefix to give to generated methods. If true, uses the attribute name. @option values [Boolean|String] :_suffix The suffix to give to generated methods. If true, uses the attribute name. @example Defining an enummer with a prefix. This would generate ‘#can_read?`, `#can_read=`, `#can_read!`, `.can_read`, etc.

enummer permissions: %i[read write execute], :_prefix: 'can'
# File lib/enummer/extension.rb, line 10
def enummer(values)
  options = {}
  options[:_prefix] = values.delete(:_prefix)
  options[:_suffix] = values.delete(:_suffix)

  name, values = values.first

  attribute(name, :enummer, value_names: values)

  singleton_class.__send__(:define_method, name) { values }

  _enummer_build_with_scope(name, values)
  _enummer_build_values(name, values, options)
end

Private Instance Methods

_enummer_affix(attribute_name, value) click to toggle source
# File lib/enummer/extension.rb, line 65
def _enummer_affix(attribute_name, value)
  return unless value
  return attribute_name if value == true

  value
end
_enummer_build_values(attribute_name, value_names, options) click to toggle source
# File lib/enummer/extension.rb, line 35
def _enummer_build_values(attribute_name, value_names, options)
  value_names.each_with_index do |name, i|
    method_name = _enummer_method_name(attribute_name, name, options)

    define_method("#{method_name}?") { self[attribute_name].include?(name) }
    define_method("#{method_name}=") do |new_value|
      if new_value
        self[attribute_name].push(name)
      else
        self[attribute_name].delete(name)
      end
    end
    define_method("#{method_name}!") do
      update(attribute_name => self[attribute_name] + [name])
    end

    bit = 1 << i

    scope method_name, -> { where("#{attribute_name} & :bit = :bit", bit: bit) }
    scope "not_#{method_name}", -> { where("#{attribute_name} & :bit != :bit", bit: bit) }
  end
end
_enummer_build_with_scope(attribute_name, value_names) click to toggle source
# File lib/enummer/extension.rb, line 27
def _enummer_build_with_scope(attribute_name, value_names)
  scope "with_#{attribute_name}", lambda { |desired|
    expected = Array.wrap(desired).sum(0) { |value| 1 << value_names.index(value) }

    where("#{attribute_name} & :expected = :expected", expected: expected)
  }
end
_enummer_method_name(attribute_name, value_name, options) click to toggle source
# File lib/enummer/extension.rb, line 58
def _enummer_method_name(attribute_name, value_name, options)
  prefix = _enummer_affix(attribute_name, options[:_prefix])
  suffix = _enummer_affix(attribute_name, options[:_suffix])

  [prefix, value_name, suffix].compact.join("_")
end