David Brady wrote: > In C++, I would use an enum for each of the values, then build arrays of > floats and strings indexed by those enums to hold the thresholds and > descriptions. That's also possible in Ruby, but I think it is a better idea to aggregate all the data into the enum member itself. Here's Ruby code for doing C++ style enums: > # Represents a C# style enumeration of known values. > # > # Usage: > # Color = Enum.new(:Red, :Green, :Blue) > # Color.is_a?(Enum) # => true > # Color::Red.inspect # => "Color::Red" > # Color::Green.is_a?(Color) # => true > # Color::Green.is_a?(Enum::Member) # => true > # Color::Green.index # => 1 > # Color::Blue.enum # => Color > # values = [[255, 0, 0], [0, 255, 0], [0, 0, 255]] > # values[Color::Green] # => [0, 255, 0] > # Color[0] # => Color::Red > # Color.size # => 3 > # > # Enums are enumerable. Enum::Members are comparable. > class Enum < Module > class Member < Module > attr_reader :enum, :index > > def initialize(enum, index) > @enum, @index = enum, index > # Allow Color::Red.is_a?(Color) > extend enum > end > > # Allow use of enum members as array indices > alias :to_int :index > alias :to_i :index > > # Allow comparison by index > def <=>(other) > @index <=> other.index > end > > include Comparable > end > > def initialize(*symbols, &block) > @members = [] > symbols.each_with_index do |symbol, index| > # Allow Enum.new(:foo) > symbol = symbol.to_s.sub(/^[a-z]/) { |letter| letter.upcase }.to_sym > member = Enum::Member.new(self, index) > const_set(symbol, member) > @members << member > end > super(&block) > end > > def [](index) @members[index] end > def size() @members.size end > alias :length :size > > def first(*args) @members.first(*args) end > def last(*args) @members.last(*args) end > > def each(&block) @members.each(&block) end > include Enumerable > end But I think it is not the best match in this case. > Struct.new("RatingData", name, threshold, description) > > RATING_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" ) > RATING_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" ) This sounds good, but I'd go with a module: module Rating Good = Struct::RatingData.new(:Good, 0.8, "Good Rating") Fair = Struct::RatingData.new(:Fair, 0.5, "Fair Rating") end That seems more Rubyish to me.