Enumerated types in Ruby

Posted by Jamis on August 07, 2005 @ 12:04 PM

It’s not often that I need an enumerated type in Ruby—there is usually a more elegant way of doing things, I’ve found. But when I’m interfacing with a C library (such as fmod, in this case), it can be a pain to stop and define constants for every enumerated type.

It’s probably been done before, but I found the following little class quite helpful:

1
2
3
4
5
6
7
8
9
10
11
12
13
class EnumeratedType
  class <<self
    def start(n)
      @next_value = n
    end

    def const_missing(sym)
      @next_value ||= 0
      const_set(sym, @next_value)
      @next_value += 1
    end
  end
end

It lets you create enumerated types like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class OutputType < EnumeratedType
  AUTODETECT
  UNKNOWN
  NOSOUND
  WAVWRITER
  DSOUND
  WINMM
  ASIO
  OSS
  ALSA
  ESD
  SOUNDMANAGER
  COREAUDIO
  XBOX
  PS2
  GC
  XBOX360
  PSP
end

If you want to start with a different integer than 0, you can just do:

1
2
3
4
5
class OutputType < EnumeratedType
  start 15
  AUTODETECT
  ...
end

You can also use start anywhere in the list, to have subsequent constants enumerated starting with the given value.

Posted in Tips & Tricks

Comments

Have something to add? Click here to leave a comment.

02 Feb 2007

1. Chuck said...

Ok this is way cool. I’m still trying to digest the syntax. You make a point of saying “there are more elegant ways of doing things…” For this particular problem, I could only come up with a hash using perhaps symbols, but I’m not convinced this is any more elegant. Did you have something else in mind when you made the comment?

2. Jamis said...

Chuck, you’ll have to give me a specific example of where you think you need enumerated types, and then let me counter it with how I’d do it in Ruby. In practice, I’ve found I only need them when interfacing with an external, native library that uses them.