· 8 years ago · Aug 04, 2018, 03:34 AM
1#
2# Use this in models for status codes etc. Will dynamically create a class constant
3# for each row in the table. The name of the constant will be based on the field specified.
4# Typically it would be code, though name might be useful in some cases.
5#
6# This will build the constants once on rails startup. It only hits the database once, the find(:all),
7# so should be reasonably efficient as long as it's used for small tables only.
8#
9# Example usage:
10#
11# class ThingType < ActiveRecord::Base
12# extend CreateIdConstants
13# create_id_constants :code
14# ...
15# end
16#
17# ThingType::FOO # => 2
18#
19# This is intended as a replacement for the technique of putting these kind of methods in
20# status and type models.
21#
22# class ThingStatus < ActiveRecord::Base
23# def self.FOO
24# @@FOO || self.find_by_code('FOO')
25# end
26# end
27#
28# ThingType.FOO.id # => 2
29#
30# Note that it gives you just the id and not the whole object. Usually you want the id anyway, so it
31# should be okay. If you do need the object, you can probably do ThingStatus.find(ThingStatus::FOO)
32# (though that wouldn't have any caching, so use sparingly).
33#
34
35module CreateIdConstants
36
37 def create_id_constants(type=:code)
38
39 self.find(:all).each do |record|
40 # Hopefully our codes don't generally have spaces or non-alpha chars.
41 # But just in case, let's replace them with underscore.
42 # Also, let's use upper case.
43 const_name = record.send(type).upcase.gsub(/[^A-Z]+/,'_')
44
45 # There are some constants we inherit from ActiveRecord. If we were really unlucky
46 # it might be possible to overwrite one of those and cause weirdness. Better not allow that.
47 # (Note: it would give an 'already initialized constant' warning, but who would ever notice that)
48 raise "Constant #{const_name} already exists" if self.const_defined?(const_name)
49
50 # Create the constant
51 self.const_set(const_name,record.id)
52 end
53
54 end
55
56end