Skip to content

Instantly share code, notes, and snippets.

@simonbaird
Created June 10, 2010 01:41
Show Gist options
  • Save simonbaird/432459 to your computer and use it in GitHub Desktop.
Save simonbaird/432459 to your computer and use it in GitHub Desktop.
#
# Use this in models for status codes etc. Will dynamically create a class constant
# for each row in the table. The name of the constant will be based on the field specified.
# Typically it would be code, though name might be useful in some cases.
#
# This will build the constants once on rails startup. It only hits the database once, the find(:all),
# so should be reasonably efficient as long as it's used for small tables only.
#
# Put this in lib/create_id_constants.rb
#
# Example usage:
#
# class ThingType < ActiveRecord::Base
# extend CreateIdConstants
# create_id_constants :code
# ...
# end
#
# ThingType::FOO # => 2
#
# This is intended as a replacement for the technique of manually putting these kind of methods in
# status and type models.
#
# class ThingStatus < ActiveRecord::Base
# def self.FOO
# @@FOO || self.find_by_code('FOO')
# end
# end
#
# ThingType.FOO.id # => 2
#
# Note that it gives you just the id and not the whole object. Usually you want the id anyway, so it
# should be okay. If you do need the object, you can probably do ThingStatus.find(ThingStatus::FOO)
# (though that wouldn't have any caching, so use sparingly).
#
# Note: If there is no data then the find returns no rows and the contants don't get set. That's probably
# sensible, but something to be aware off in case things don't work as you expect.
#
module CreateIdConstants
def create_id_constants(use_column=:code)
self.find(:all).each do |record|
# Hopefully our codes don't generally have spaces or non-alpha chars.
# But just in case, let's replace them with underscore.
# Also, let's use upper case.
const_name = record.send(use_column.to_sym).upcase.gsub(/[^A-Z]+/,'_')
# There are some constants we inherit from ActiveRecord. If we were really unlucky
# it might be possible to overwrite one of those and cause weirdness. Better not allow that.
# (Note: it would give an 'already initialized constant' warning, but who would ever notice that)
raise "Constant #{const_name} already exists" if self.const_defined?(const_name)
# Create the constant
self.const_set(const_name,record.id)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment