module EnumX::DSL

Mixin for any ActiveRecord or ActiveModel object to support enums.

Usage

First, make sure your model class includes EnumX::DSL:

include EnumX::DSL

Then, define any enum-like attribute using the {#enum} method. The best enum is always inferred. The following are identical:

enum :status, :statuses
enum :status, EnumX.statuses
enum :status, EnumX[:statuses]
enum :status

The latter infers the 'statuses' enum by default. If no applicable enum was found, an error is thrown.

Multi-enums

Specify the option +:flags => true+ to allow the attribute to contain multiple enum values at once. The attribute will in essence become an array.

@see ClassMethods#enum

Public Class Methods

define_mnemonics(target, attribute, enum) click to toggle source

Mnemonics (single & multi)

# File lib/enum_x/dsl.rb, line 349
      def self.define_mnemonics(target, attribute, enum)
        enum.values.each do |value|
          target.class_eval <<-RUBY, __FILE__, __LINE__+1
            def #{value}?
              :#{value} === #{attribute}
            end
          RUBY
        end
      end
define_multi_reader(target, attribute) click to toggle source

Multi enum reader & writer

# File lib/enum_x/dsl.rb, line 321
      def self.define_multi_reader(target, attribute)
        define_reader target, attribute, <<-RUBY
          enum = EnumX.find(self.class, :#{attribute.to_s})
          case value = %{read_value}
          when nil then nil
          when EnumX::ValueList then value
          when Enumerable then EnumX::ValueList.new(enum, value)
          else EnumX::ValueList.new(enum, [value])
          end
        RUBY
      end
define_multi_writer(target, attribute) click to toggle source
# File lib/enum_x/dsl.rb, line 333
      def self.define_multi_writer(target, attribute)
        define_writer target, attribute, <<-RUBY
          enum = EnumX.find(self.class, :#{attribute.to_s})
          value = case value
          when nil then nil
          when EnumX::ValueList then value
          when Enumerable then EnumX::ValueList.new(enum, value)
          else EnumX::ValueList.new(enum, [value])
          end
          %{write_value}
        RUBY
      end
define_reader(target, attribute, body) click to toggle source

Defines a generic attribute reader ActiveModel-like classes. @api private

# File lib/enum_x/dsl.rb, line 225
      def self.define_reader(target, attribute, body)
        override = target.instance_methods.include?(attribute.to_sym)

        value_reader = case true
        when override
          "#{attribute}_without_enums"
        when target.instance_methods.include?(:read_attribute) || target.private_instance_methods.include?(:read_attribute)
          "read_attribute(:#{attribute})"
        else
          # We need a reader to fall back to.
          raise "cannot overwrite enum reader - no existing reader found"
        end

        body.gsub! '%{read_value}', value_reader

        if override
          target.class_eval <<-RUBY, __FILE__, __LINE__+1
            def #{attribute}_with_enums
              #{body}
            end
            alias_method_chain :#{attribute}, :enums
          RUBY
        else
          target.class_eval <<-RUBY, __FILE__, __LINE__+1
            def #{attribute}
              #{body}
            end
          RUBY
        end
      end
define_single_reader(target, attribute) click to toggle source

Single enum reader & writer

# File lib/enum_x/dsl.rb, line 293
      def self.define_single_reader(target, attribute)
        define_reader target, attribute, <<-RUBY
          case value = %{read_value}
          when EnumX::Value then value
          when nil then nil
          else
            enum = EnumX.find(self.class, :#{attribute.to_s.pluralize})
            enum[value] || value
          end
        RUBY
      end
define_single_writer(target, attribute) click to toggle source
# File lib/enum_x/dsl.rb, line 305
      def self.define_single_writer(target, attribute)
        define_writer target, attribute, <<-RUBY
          value = case value
          when EnumX::Value then value
          when nil then nil
          else
            enum = EnumX.find(self.class, :#{attribute.to_s.pluralize})
            enum[value] || value
          end
          %{write_value}
        RUBY
      end
define_writer(target, attribute, body) click to toggle source

Defines a generic attribute writer ActiveModel-like classes. @api private

# File lib/enum_x/dsl.rb, line 258
      def self.define_writer(target, attribute, body)
        method = :"#{attribute}="
        override = target.instance_methods.include?(method)

        value_writer = case true
        when override
          "self.#{attribute}_without_enums = value"
        when target.instance_methods.include?(:write_attribute) || target.private_instance_methods.include?(:write_attribute)
          "write_attribute :#{attribute}, value"
        else
          # We need a writer to fall back to.
          raise "cannot overwrite enum writer - no existing writer found"
        end

        body.gsub! '%{write_value}', value_writer

        if override
          target.class_eval <<-RUBY, __FILE__, __LINE__+1
            def #{attribute}_with_enums=(value)
              #{body}
            end
            alias_method_chain :#{attribute}=, :enums
          RUBY
        else
          target.class_eval <<-RUBY, __FILE__, __LINE__+1
            def #{attribute}=(value)
              #{body}
            end
          RUBY
        end
      end
included(target) click to toggle source
# File lib/enum_x/dsl.rb, line 30
def self.included(target)
  target.extend ClassMethods
end