module PowerEnum::HasEnumerated::ClassMethods

Class-level behavior injected into ActiveRecord to support has_enumerated

Public Instance Methods

enumerated_attributes() click to toggle source

Returns a list of all the attributes on the ActiveRecord model which are enumerated.

# File lib/power_enum/has_enumerated.rb, line 16
def enumerated_attributes
  @enumerated_attributes ||= []
end
has_enumerated(part_id, options = {}) click to toggle source

Defines an enumerated attribute with the given attribute_name on the model. Also accepts a hash of options as an optional second argument.

Supported options

:class_name

Name of the enum class. By default it is the camelized version of the has_enumerated attribute.

:foreign_key

Explicitly set the foreign key column. By default it’s assumed to be your_enumerated_attribute_name_id.

:on_lookup_failure

The :on_lookup_failure option in has_enumerated is there because you may want to create an error handler for situations where the argument passed to status=(arg) is invalid. By default, an invalid value will cause an ArgumentError to be raised. Since this may not be optimal in your situation, you can do one of three things:

1) You can set it to ‘validation_error’. In this case, the invalid value will be cached and returned on subsequent lookups, but the model will fail validation. 2) You can specify an instance method to be called in the case of a lookup failure. The method signature is as follows:

<tt>your_lookup_handler(operation, attribute_name, name_foreign_key, acts_enumerated_class_name, lookup_value)</tt>

The ‘operation’ arg will be either :read or :write. In the case of :read you are expected to return something or raise an exception, while in the case of a :write you don’t have to return anything. Note that there’s enough information in the method signature that you can specify one method to handle all lookup failures for all has_enumerated fields if you happen to have more than one defined in your model. ‘NOTE’: A nil is always considered to be a valid value for status=(arg) since it’s assumed you’re trying to

null out the foreign key. The :on_lookup_failure method will be bypassed.

3) You can give it a lambda function. In that case, the lambda needs to accept the ActiveRecord model as its first argument, with the rest of the arguments being identical to the signature of the lookup handler instance method.

:permit_empty_name

Setting this to ‘true’ disables automatic conversion of empty strings to nil. Default is ‘false’.

:default

Setting this option will generate an after_initialize callback to set a default value on the attribute unless a non-nil one already exists.

:create_scope

Setting this option to ‘false’ will disable automatically creating ‘with_enum_attribute’ and ‘exclude_enum_attribute’ scope.

Example

class Booking < ActiveRecord::Base
  has_enumerated  :status,
                  :class_name        => 'BookingStatus',
                  :foreign_key       => 'status_id',
                  :on_lookup_failure => :optional_instance_method,
                  :permit_empty_name => true,
                  :default           => :unconfirmed,
                  :create_cope       => false
end

Example 2

class Booking < ActiveRecord::Base
  has_enumerated  :booking_status,
                  :class_name        => 'BookingStatus',
                  :foreign_key       => 'status_id',
                  :on_lookup_failure => lambda{ |record, op, attr, fk, cl_name, value|
                    # handle lookup failure
                  }
end
# File lib/power_enum/has_enumerated.rb, line 84
def has_enumerated(part_id, options = {})
  options.assert_valid_keys(:class_name,
                            :foreign_key,
                            :on_lookup_failure,
                            :permit_empty_name,
                            :default,
                            :create_scope)

  # Add a reflection for the enumerated attribute.
  reflection = create_ar_reflection(part_id, options)

  attribute_name   = part_id.to_s
  class_name       = reflection.class_name
  foreign_key      = reflection.foreign_key
  failure_opt      = options[:on_lookup_failure]
  allow_empty_name = options[:permit_empty_name]
  create_scope     = options[:create_scope]

  failure_handler = get_lookup_failure_handler(failure_opt)

  class_attribute "has_enumerated_#{attribute_name}_error_handler"
  self.send("has_enumerated_#{attribute_name}_error_handler=", failure_handler)

  define_enum_accessor attribute_name, class_name, foreign_key, failure_handler
  define_enum_writer attribute_name, class_name, foreign_key, failure_handler, allow_empty_name

  if failure_opt.to_s == 'validation_error'
    define_validation_error(attribute_name)
  end

  enumerated_attributes << attribute_name

  if options.has_key?(:default)
    define_default_enum_value(attribute_name, options[:default])
  end

  unless create_scope == false
    define_enum_scope(attribute_name, class_name, foreign_key)
  end

end
has_enumerated?(attribute) click to toggle source

Returns true if attribute is an enumerated attribute, false otherwise.

# File lib/power_enum/has_enumerated.rb, line 21
def has_enumerated?(attribute)
  return false if attribute.nil?
  enumerated_attributes.include? attribute.to_s
end

Private Instance Methods

create_ar_reflection(part_id, options) click to toggle source

Creates the ActiveRecord reflection

# File lib/power_enum/has_enumerated.rb, line 129
        def create_ar_reflection(part_id, options)
  reflection = PowerEnum::Reflection::EnumerationReflection.new(part_id, options, self)

  self._reflections = self._reflections.merge(part_id.to_s => reflection)
  reflection
end