Robert Klemme
2/21/2006 9:46:00 AM
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