From: Robert Klemme Date: 2006-02-21T18:48:37+09:00 Subject: Re: Idiomatic Ruby: Enumerations listrecv@gmail.com wrote: > Hi. I'd appreciate comments/criticisms on the following approach & > code: > > For some variables, we need to be able to choose from enumerations. > For instance, we track different choices on a webform - each has an > integer code, as well as some other properties. I want to implement a > class which these are made out of. > > How's this?: > > class TimeSlot > > # Only use predefined > private_class_method :new > > # The text description > attr_reader :text > > # The integer code > attr_reader :code > > # The legacy_id (key in a legacy database) > attr_reader :legacy_id > > def initialize(text, code, legacy_id) > @text = text > @code = code > @legacy_id = legacy_id > end > > MORNING = new('morning', 2, 1001) > AFTERNOON = new('morning', 3, 1002) > EVENING = new('evening', 4, 1003) > NIGHT = new('night', 5, 1004') > > # This next line is unDRY, but I'm not sure how to eliminate > it. > # Perhaps instead of just listing the constansts, use a > register_value method which both defines the constant > # and adds it to the @@values - but I'm not sure how to > implement this > @@members = [MORNING, AFTERNOON, EVENING, NIGHT] I would not use a class variable here as it does not seem needed. A simple class member will be sufficient. As for the definition method: def self.enum(*a) c = new(*a).freeze (@members || = []) << c c end Then you can do MORNING = enum 'morning', 2, 1001 OTOH, you do not need this at all. You can simply use TimeSlot.constants to get all constants defined in this class. If you need to be more selective (foe example if you define nested classes in this class) you can do def self.enums constants.select {|x| self === x} end Which will select only instances of TimeSlot. > def self.from_code(c) > @@members.find { |t| t.code == c } || raise ArgumentError, "No > TimeSlot has code #{c}" > end > > end > > Also - we have several of these - how would I extract a common > Enumeration mixin? I'd like to be able to include Enumeration, much > as you include Singleton, to turn a class into an enumeration type > along these lines. I think I've seen an enumeration module on RAA. If not it will be quite easy to put some code in a module and implement YourModule#included or YourModule#extended to make certain changes (like making new private). HTH Kind regards robert