module AttributeHelpers

Provides helper functionality for ruby classes that store various database-unfriendly types as instance variables. It automatically serializes and deserializes things like classes and symbols to interact easily with both the database and your application code.

Constants

VERSION

Public Instance Methods

attr_class(*attrs) click to toggle source
# File lib/attribute_helpers.rb, line 13
def attr_class(*attrs)
  transform_attributes(*attrs) { |val| Kernel.const_get(val) }
end
attr_symbol(*attrs) click to toggle source
# File lib/attribute_helpers.rb, line 9
def attr_symbol(*attrs)
  transform_attributes(*attrs, &:to_sym)
end
transform_attributes(*attrs, &block) click to toggle source

Implementation Note


The transformers above all work by creating an anonymous module for each group of attributes that gets prepended into the class the AttributeHelpers module is included into. These modules need to be defined at method call time to avoid leaking the overrided methods into other classes this module is included in.

This anonymous module needs to be prepended to work in ActiveRecord classes. This is because ActiveRecord doesn’t have accessors/mutators defined until an instance is created, which means we need to use the prepend pattern because attempts to use instance_method instance_method will not find the method in the class context as it will not exist until it is dynamically created when an instance is created. Prepend works for us because it inserts the behavior below the class in the inheritance hierarchy, so we can access the default ActiveRecord accessors/ mutators through the use of super().

More information here: stackoverflow.com/a/4471202/1103543

Calls superclass method
# File lib/attribute_helpers.rb, line 36
def transform_attributes(*attrs, &block)
  transformer = Module.new do
    attrs.each do |attr|
      # Overwrite the accessor.
      define_method(attr) do
        val = super()
        val && block.call(val)
      end

      # Overwrite the mutator.
      define_method("#{attr}=") do |val|
        super(val && val.to_s)
      end
    end
  end

  prepend transformer
end