dry

Ruby mixin for the Enum pattern

Sometimes you just want to use an Enum. Unfortunately, if you're a Ruby developer, Ruby does not offer a native enum structure. Here's a simple approach using a mixin module:

module Enum
  def const_missing(key)
    @enum_hash[key]
  end
 
  def add_enum(key, value)
    @enum_hash ||= {}
    @enum_hash[key] = NameValuePair.new(value, key.to_s.downcase)
  end
 
  def each
    @enum_hash.each {|key, value| yield(key, value) }
  end
 
  def enums
    @enum_hash.keys
  end
 
  def enum_values
    @enum_hash.values
  end
 
  def get_enum_hash
    @enum_hash
  end
 
  def find_by_key(key)
    @enum_hash[key.upcase.to_sym]
  end
end

The Enum mixin depends on a NameValuePair class to hold the data:

class NameValuePair
  attr_reader :label, :value
 
  def initialize(label, value)
    @label = label
    @value = value
  end
 
  def first
    @label
  end
 
  def last
    @value
  end
end

I included first and last methods to better support the select and options_for_select helper methods in Rails. Here's how you might use it:

class FooEnum
  extend Enum
 
   self.add_enum(:APPLE, "Apple")
   self.add_enum(:PEAR, "Pear")
   self.add_enum(:ALL, "All Fruit")
end
 
FooEnum::APPLE ==> #<NameValuePair @value="apple", @label="Apple">
FooEnum::ALL.value ==> "all"
FooEnum::ALL.label ==> "All Fruit"
FooEnum.find_by_key('apple') ==> #<NameValuePair @value="apple", @label="Apple">

DRY Associations in Rails

I found a nice little article from a few months ago on The Rails Way. Written by koz, Assocation Proxies talks about some Best Practices for using assocations within Rails. I really felt the suggestions hit the proverbial nail on the head in terms of following the DRY principles. The first suggestion was on the best way to restrict access to user specific information. It's incredibly useful to take advantage your RESTful patterns and make a single call like:

Syndicate content