· 8 years ago · May 28, 2018, 03:54 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# Put this in lib/create_id_constants.rb
10#
11# Example usage:
12#
13# class ThingType < ActiveRecord::Base
14# extend CreateIdConstants
15# create_id_constants :code
16# ...
17# end
18#
19# ThingType::FOO # => 2
20#
21# This is intended as a replacement for the technique of manually putting these kind of methods in
22# status and type models.
23#
24# class ThingStatus < ActiveRecord::Base
25# def self.FOO
26# @@FOO || self.find_by_code('FOO')
27# end
28# end
29#
30# ThingType.FOO.id # => 2
31#
32# Note that it gives you just the id and not the whole object. Usually you want the id anyway, so it
33# should be okay. If you do need the object, you can probably do ThingStatus.find(ThingStatus::FOO)
34# (though that wouldn't have any caching, so use sparingly).
35#
36# Note: If there is no data then the find returns no rows and the contants don't get set. That's probably
37# sensible, but something to be aware off in case things don't work as you expect.
38#
39
40module CreateIdConstants
41
42 def create_id_constants(use_column=:code)
43
44 self.find(:all).each do |record|
45 # Hopefully our codes don't generally have spaces or non-alpha chars.
46 # But just in case, let's replace them with underscore.
47 # Also, let's use upper case.
48 const_name = record.send(use_column.to_sym).upcase.gsub(/[^A-Z]+/,'_')
49
50 # There are some constants we inherit from ActiveRecord. If we were really unlucky
51 # it might be possible to overwrite one of those and cause weirdness. Better not allow that.
52 # (Note: it would give an 'already initialized constant' warning, but who would ever notice that)
53 raise "Constant #{const_name} already exists" if self.const_defined?(const_name)
54
55 # Create the constant
56 self.const_set(const_name,record.id)
57 end
58
59 end
60
61end