Forum: Ruby Enumerated Types

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dan Stevens (IAmAI) (Guest)
on 2007-02-03 20:53
(Received via mailing list)
As part of a solution, I wish the value of an attribute to be one of a
finite set of values, in other words I believe I want an 'enumerated
type'. I've look at the 'Enumerable' and 'Enumerator' class and they
appear to me to be unrelated to what I wish to achieve (correct me if
I'm wrong).

I could do the traditional method of named constants with integer
values but I can't help feeling that there must be a class or some
nice method of doing this. Any advice would be appreciated.
Robert K. (Guest)
on 2007-02-03 21:01
(Received via mailing list)
On 03.02.2007 19:52, Dan Stevens (IAmAI) wrote:
> As part of a solution, I wish the value of an attribute to be one of a
> finite set of values, in other words I believe I want an 'enumerated
> type'. I've look at the 'Enumerable' and 'Enumerator' class and they
> appear to me to be unrelated to what I wish to achieve (correct me if
> I'm wrong).
>
> I could do the traditional method of named constants with integer
> values but I can't help feeling that there must be a class or some
> nice method of doing this. Any advice would be appreciated.

I believe there are enum classes in the RAA.  If you do not want to use
them, symbols come pretty close:

class YourClass
   YOUR_ENUM = [
     :old,
     :young,
     :unknown,
   ].freeze
end

HTH

Kind regards

  robert
Dan Stevens (IAmAI) (Guest)
on 2007-02-05 21:55
(Received via mailing list)
It seems to me that I should simply be able to use symbols as values
for my enumerated types, like for example:

class Color

  def initialize(color)
    @color = color
  end

  def to_hex
    case @color
      when :red: 0xFF0000
      when :green: 0x00FF00
      when :blue: 0x0000FF
      else @color
    end
  end

end

c = Color.new(:red)
puts c.to_hex.to_s(16)

Might there be any reason why I shouldn't do this, or am I quite fine
doing this?
Logan C. (Guest)
on 2007-02-05 22:07
(Received via mailing list)
On 2/5/07, Dan Stevens (IAmAI) <removed_email_address@domain.invalid> wrote:
>   def to_hex
> c = Color.new(:red)
> puts c.to_hex.to_s(16)
>
> Might there be any reason why I shouldn't do this, or am I quite fine
> doing this?


This is fine. You may want to use a hash to make life simpler though:
class Color
  HexValues = { :red  =>  0xFF0000, :green => 0x00FF00, :blue =>
0x0000FF }
  def to_hex
     HexValues[@color] or @color
  end
end
Garance A Drosehn (Guest)
on 2007-02-06 01:34
(Received via mailing list)
On 2/3/07, Dan Stevens (IAmAI) <removed_email_address@domain.invalid> wrote:
> As part of a solution, I wish the value of an attribute to be one of a
> finite set of values, in other words I believe I want an 'enumerated
> type'. I've look at the 'Enumerable' and 'Enumerator' class and they
> appear to me to be unrelated to what I wish to achieve (correct me if
> I'm wrong).
>
> I could do the traditional method of named constants with integer
> values but I can't help feeling that there must be a class or some
> nice method of doing this. Any advice would be appreciated.

I picked up this snippet of code:

# -------+---------+---------+-------- +
--------+---------+---------+---------+
#   Add methods enum and bit_enum to the Object class, thus making it
much
#   easier and less error-prone to define a long list of constants in a
#   class.  This idea comes from Ara.T.Howard@noaa, in a posting to
ruby-talk
#   on August 2, 2005 (in reply to a question).  These work very nicely
with
#   a word-list array as generated via %w().  Very clever!
#
class Object
    def enum_constants(*list)
  mc = Module === self ? self : self.class
  list.flatten.each_with_index{|e, i| mc.const_set e.to_s.intern, i}
    end
    def enum_bit_constants(*list)
  mc = Module === self ? self : self.class
  list.flatten.each_with_index{|e, i| mc.const_set e.to_s.intern, 2 **
i}
    end
end
# -------+---------+---------+-------- +
--------+---------+---------+---------+

An example of using it:

    #   Constants that define all categories of packets which we
recognize.
    enum_constants %w(
    SBC_NONE  SBC_ARRAY  SBC_NONUSER  SBC_NO_IDSTR
    SBC_IGNFAIL   SBC_ALL
    SBC_UNMATCHED )

The difference between enum_constants() and enum_bit_constants is
that enum_constants will define the values as 1, 2, 3, 4, 5, etc, while
enum_bit_constants will define them as 1,2,4,8,16,32.  You can 'or'
the enum_bit_constant values together, and each one is a separate
bit so it won't clobber any other bit constant.

If you are not used to the %w() method of quoting, note that you only
put the names you want in there.  You do *not* separate them with
commas!
Robert K. (Guest)
on 2007-02-06 22:46
(Received via mailing list)
On 05.02.2007 20:54, Dan Stevens (IAmAI) wrote:
>    case @color
> puts c.to_hex.to_s(16)
>
> Might there be any reason why I shouldn't do this, or am I quite fine
> doing this?

That's perfectly ok.  If you need your enums only for mapping then I'd
probably do this:

Color = Struct.new :name do
   CODES = Hash.new {|h,k| k}.update(
     :red => 0xFF0000,
     :green => 0x00FF00
     # ...
   )

   def to_hex; CODES[name] end
end

irb(main):010:0> Color.new(:red).to_hex.to_s 16
=> "ff0000"

If you need more enum dependent behavior you might want put more complex
objects into the hash instead of only Fixnums.

Kind regards

  robert
This topic is locked and can not be replied to.