Idiomatic Ruby: Enumerations

Discussion in 'Ruby' started by listrecv@gmail.com, Feb 21, 2006.

  1. Guest

    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]

    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.
     
    , Feb 21, 2006
    #1
    1. Advertising

  2. 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
     
    Robert Klemme, Feb 21, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Iwan van der Kleyn
    Replies:
    5
    Views:
    162
    James Edward Gray II
    Nov 23, 2004
  2. Zed A. Shaw
    Replies:
    2
    Views:
    112
    Zed A. Shaw
    Apr 23, 2005
  3. Brock Weaver

    Idiomatic ruby version of this code?

    Brock Weaver, Aug 18, 2005, in forum: Ruby
    Replies:
    16
    Views:
    181
    pat eyler
    Aug 23, 2005
  4. Idiomatic ruby

    , Feb 12, 2006, in forum: Ruby
    Replies:
    5
    Views:
    122
    Robert Klemme
    Feb 13, 2006
  5. Replies:
    0
    Views:
    140
Loading...

Share This Page