# Ruby idiom for enum?

**URL:** <https://rubytalk.org/t/ruby-idiom-for-enum/20444>\
**Category:** ruby-talk\
**Created:** [28 August 2005 04:40 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444 "2005-08-28T04:40:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![David\_Brady](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Brady](https://rubytalk.org/u/David_Brady)\
**Post date:** [28 August 2005 04:40 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/1 "2005-08-28T04:40:45Z")

</div>

Okay, one more question from a C++ leopard trying to change his spots:

I want to set up a program that uses some predefined values to determine its logic. For example, a method could analyze some data and return "Good", "Fair", "Poor", or "Out of Bounds" based on a set of thresholds. I want to be able to refer to these values by name in my code, so constants or symbols make a good choice here. But I also want to build a sort of rule set around these values: some function returns values in the range of (0.0..1.0) and I want to be able to say that 0.8 is the minimum score for "Good", etc. I also want the word "Good" stored in a specific single place so that I don't make any typos each time I need to print the description.

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.

What's the Ruby idiom for this?

Perhaps Struct followed by some initializer arrays? This seems like a good start but I end up wanting to build a set of constants first to use as keys to a hash containing the Structs. Perhaps the Structs should be the constants themselves, like:

Struct.new("RatingData", name, threshold, description)

RATING\_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )  
RATING\_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )

...etc. The analyze\_data could return RATING\_GOOD if things were fine. So:

rating = analyze\_data data  
puts "Analysis: #{rating.description}"

Though this doesn't let me treat the values as though they are ordered, e.g.

puts "\*\*\* Warning: Rating below Fair \*\*\*" if rating \< RATING\_FAIR

Thoughts?

-dB

> **···**
>
> --  
> David Brady  
> [ruby-talk@shinybit.com](mailto:ruby-talk@shinybit.com)  
> I'm having a really surreal day... OR AM I?

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [28 August 2005 10:19 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/2 "2005-08-28T10:19:21Z")

</div>

There are several possible solutions: Use an enum lib maybe there's  
something in the RAA  
[http://raa.ruby-lang.org/search.rhtml?search=enum](http://raa.ruby-lang.org/search.rhtml?search=enum)

Or create a Hash with nested Arrays

RATINGS = {  
&nbsp;&nbsp;:good =\> [0.8, "Good Rating"],  
&nbsp;&nbsp;:bad =\> [0.1, "Bad Rating"]  
}

I'd probably go with your struct approach with some additional code  
for creation of a single rating that will also register all ratings  
somewhere and with some algorithm for determining the rating.

For example, if you place your constants in class Struct::RatingData  
you can easily get all ratings via Struct::RatingData.constants.

If you need efficient rating assignment from a float value and if  
there are many ratings then you might want to store ratings ordered by  
the threshold to use binary search on the ratings to find the correct  
one.

Just some thoughts.

Kind regards

robert

> **···**
>
> 2005/8/28, David Brady \<ruby\_talk@shinybit.com\>:
> 
> > Okay, one more question from a C++ leopard trying to change his spots:
> > 
> > I want to set up a program that uses some predefined values to determine  
> > its logic. For example, a method could analyze some data and return  
> > "Good", "Fair", "Poor", or "Out of Bounds" based on a set of  
> > thresholds. I want to be able to refer to these values by name in my  
> > code, so constants or symbols make a good choice here. But I also want  
> > to build a sort of rule set around these values: some function returns  
> > values in the range of (0.0..1.0) and I want to be able to say that 0.8  
> > is the minimum score for "Good", etc. I also want the word "Good"  
> > stored in a specific single place so that I don't make any typos each  
> > time I need to print the description.
> > 
> > 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.
> > 
> > What's the Ruby idiom for this?
> > 
> > Perhaps Struct followed by some initializer arrays? This seems like a  
> > good start but I end up wanting to build a set of constants first to use  
> > as keys to a hash containing the Structs. Perhaps the Structs should be  
> > the constants themselves, like:
> > 
> > Struct.new("RatingData", name, threshold, description)
> > 
> > RATING\_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )  
> > RATING\_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )
> > 
> > ...etc. The analyze\_data could return RATING\_GOOD if things were fine. So:
> > 
> > rating = analyze\_data data  
> > puts "Analysis: #{rating.description}"
> > 
> > Though this doesn't let me treat the values as though they are ordered, e.g.
> > 
> > puts "\*\*\* Warning: Rating below Fair \*\*\*" if rating \< RATING\_FAIR
> > 
> > Thoughts?

---

<div class="post-metadata">

**Author:** ![Brian\_Schroder1](https://avatars.discourse-cdn.com/v4/letter/b/2bfe46/32.png) [@Brian\_Schroder1](https://rubytalk.org/u/Brian_Schroder1)\
**Post date:** [28 August 2005 11:53 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/3 "2005-08-28T11:53:00Z")

</div>

Simply expanding on your thoughts:

--------8\<--------8\<--------  
module RATING  
&nbsp;&nbsp;RatingData = Struct.new(:name, :threshold, :description)

&nbsp;&nbsp;class RatingData  
&nbsp;&nbsp;&nbsp;&nbsp;include Comparable

&nbsp;&nbsp;&nbsp;&nbsp;def \<=\>(o)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o.respond\_to?:threshold  
&nbsp;&nbsp;self.threshold \<=\> o.threshold  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;self.threshold \<=\> o  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;GOOD = RatingData.new( :Good, 0.8, "Good Rating" )  
&nbsp;&nbsp;FAIR = RatingData.new( :Fair, 0.5, "Fair Rating" )  
&nbsp;&nbsp;POOR = RatingData.new( :Poor, 0.2, "Poor Rating" )  
end

rating = RATING::POOR  
puts "Analysis: #{rating.description}"

puts "\*\*\* Warning: Rating below Fair \*\*\*" if rating \< RATING::FAIR  
--------8\<--------8\<--------

would be a possibility. Throw in some metaprogramming and it can get  
really nice.

regards,

Brian

> **···**
>
> On 28/08/05, David Brady \<ruby\_talk@shinybit.com\> wrote:
> 
> > Okay, one more question from a C++ leopard trying to change his spots:
> > 
> > I want to set up a program that uses some predefined values to determine  
> > its logic. For example, a method could analyze some data and return  
> > "Good", "Fair", "Poor", or "Out of Bounds" based on a set of  
> > thresholds. I want to be able to refer to these values by name in my  
> > code, so constants or symbols make a good choice here. But I also want  
> > to build a sort of rule set around these values: some function returns  
> > values in the range of (0.0..1.0) and I want to be able to say that 0.8  
> > is the minimum score for "Good", etc. I also want the word "Good"  
> > stored in a specific single place so that I don't make any typos each  
> > time I need to print the description.
> > 
> > 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.
> > 
> > What's the Ruby idiom for this?
> > 
> > Perhaps Struct followed by some initializer arrays? This seems like a  
> > good start but I end up wanting to build a set of constants first to use  
> > as keys to a hash containing the Structs. Perhaps the Structs should be  
> > the constants themselves, like:
> > 
> > Struct.new("RatingData", name, threshold, description)
> > 
> > RATING\_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )  
> > RATING\_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )
> > 
> > ...etc. The analyze\_data could return RATING\_GOOD if things were fine. So:
> > 
> > rating = analyze\_data data  
> > puts "Analysis: #{rating.description}"
> > 
> > Though this doesn't let me treat the values as though they are ordered, e.g.
> > 
> > puts "\*\*\* Warning: Rating below Fair \*\*\*" if rating \< RATING\_FAIR
> > 
> > Thoughts?
> 
> --  
> [http://ruby.brian-schroeder.de/](http://ruby.brian-schroeder.de/)
> 
> Stringed instrument chords: [http://chordlist.brian-schroeder.de/](http://chordlist.brian-schroeder.de/)

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard6](https://avatars.discourse-cdn.com/v4/letter/a/958977/32.png) [@Ara.T.Howard6](https://rubytalk.org/u/Ara.T.Howard6)\
**Post date:** [28 August 2005 14:58 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/4 "2005-08-28T14:58:52Z")

</div>

> Okay, one more question from a C++ leopard trying to change his spots:
> 
> I want to set up a program that uses some predefined values to determine its  
> logic. For example, a method could analyze some data and return "Good",  
> "Fair", "Poor", or "Out of Bounds" based on a set of thresholds. I want to  
> be able to refer to these values by name in my code, so constants or symbols  
> make a good choice here. But I also want to build a sort of rule set around  
> these values: some function returns values in the range of (0.0..1.0) and I  
> want to be able to say that 0.8 is the minimum score for "Good", etc. I  
> also want the word "Good" stored in a specific single place so that I don't  
> make any typos each time I need to print the description.
> 
> 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.
> 
> What's the Ruby idiom for this?

you could use enums : it's easy enough to do clearly in ruby

&nbsp;&nbsp;&nbsp;[http://groups.google.com/group/comp.lang.ruby/browse\_thread/thread/6f37e998434e65e5/ea5a7cc77156ee36?q=ara+howard+enum&rnum=1#ea5a7cc77156ee36](http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/6f37e998434e65e5/ea5a7cc77156ee36?q=ara+howard+enum&rnum=1#ea5a7cc77156ee36)

> Perhaps Struct followed by some initializer arrays? This seems like a good  
> start but I end up wanting to build a set of constants first to use as keys  
> to a hash containing the Structs. Perhaps the Structs should be the  
> constants themselves, like:
> 
> Struct.new("RatingData", name, threshold, description)
> 
> RATING\_GOOD = Struct::RatingData( :Good, 0.8, "Good Rating" )  
> RATING\_FAIR = Struct::RatingData( :Fair, 0.5, "Fair Rating" )
> 
> ...etc. The analyze\_data could return RATING\_GOOD if things were fine. So:
> 
> rating = analyze\_data data  
> puts "Analysis: #{rating.description}"
> 
> Though this doesn't let me treat the values as though they are ordered, e.g.

i often do something like this:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class C  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module RATING  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIST = [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GOOD = 'GOOD',  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FAIR = 'FAIR',  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;POOR = 'POOR',  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAITINGS = RATING::LIST  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p C::RATING::GOOD  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p C::RAITINGS  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C::RAITINGS.each{|r| p r}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"GOOD"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;["GOOD", "FAIR", "POOR"]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"GOOD"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"FAIR"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"POOR"

remember - the main reason to use ints for enums in c/c++ is to be able to use  
'==' with the variables but a language like ruby can do just as well with  
strings.

> puts "\*\*\* Warning: Rating below Fair \*\*\*" if rating \< RATING\_FAIR
> 
> Thoughts?

in any case, reading over your description i'd be inclined to wrap Raitings as  
as objects and design a class generator that sets appropriate constants to  
configurable raitings, something like:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> cat a.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module RuleSet  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Raiting  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;include Comparable  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attr 'description'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attr 'value'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def initialize d, v  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@description, @value = String(d), Float(v)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def \<=\> other  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ov = other.value rescue other  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value \<=\> ov  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"#{ description }(#{ value })"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias inspect to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module ClassMehods  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attr 'raitings'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def inspect; raitings.inspect; end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def to\_s; raitings.inspect; end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module InstanceMethods  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< self  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def new(spec = {'good' =\> 0.8, 'fair' =\> 0.5, 'poor' =\> 0.2,})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;klass = Class::new {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;include InstanceMethods  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extend ClassMehods  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@raitings =   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%w( good fair poor ).each do |k|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c = k.upcase  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ks = k.to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ki = ks.intern  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys = [k, ki, ks.downcase, ks.upcase]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v = nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys.each{|k| v = spec[k] and break}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r = Raiting::new k, v  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const\_set c, r  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@raitings \<\< r  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias new  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rule\_set = RuleSet::new  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p rule\_set::raitings  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p(rule\_set::GOOD \< 42)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p rule\_set::GOOD.description  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p rule\_set::GOOD.value

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs =  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RuleSet[  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:good =\> 42,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:fair =\> 41,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:poor =\> 40,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p rs  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p(rs::GOOD == 42)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;harp:~ \> ruby a.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[good(0.8), fair(0.5), poor(0.2)]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"good"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.8  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[good(42.0), fair(41.0), poor(40.0)]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true

hth.

-a

> **···**
>
> # On Sun, 28 Aug 2005, David Brady wrote: --
> 
> > email :: ara [dot] t [dot] howard [at] noaa [dot] gov  
> > phone :: 303.497.6469  
> > Your life dwells amoung the causes of death  
> > Like a lamp standing in a strong breeze. --Nagarjuna
> 
> ===============================================================================

---

<div class="post-metadata">

**Author:** ![Florian\_Gross2](https://avatars.discourse-cdn.com/v4/letter/f/b4bc9f/32.png) [@Florian\_Gross2](https://rubytalk.org/u/Florian_Gross2)\
**Post date:** [28 August 2005 15:04 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/5 "2005-08-28T15:04:13Z")

</div>

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  
> &nbsp;&nbsp;class Member \< Module  
> &nbsp;&nbsp;&nbsp;&nbsp;attr\_reader :enum, :index
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def initialize(enum, index)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@enum, @index = enum, index  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Allow Color::Red.is\_a?(Color)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extend enum  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;# Allow use of enum members as array indices  
> &nbsp;&nbsp;&nbsp;&nbsp;alias :to\_int :index  
> &nbsp;&nbsp;&nbsp;&nbsp;alias :to\_i :index
> 
> &nbsp;&nbsp;&nbsp;&nbsp;# Allow comparison by index  
> &nbsp;&nbsp;&nbsp;&nbsp;def \<=\>(other)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@index \<=\> other.index  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;include Comparable  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def initialize(\*symbols, &block)  
> &nbsp;&nbsp;&nbsp;&nbsp;@members =   
> &nbsp;&nbsp;&nbsp;&nbsp;symbols.each\_with\_index do |symbol, index|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Allow Enum.new(:foo)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;symbol = symbol.to\_s.sub(/^[a-z]/) { |letter| letter.upcase }.to\_sym  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;member = Enum::Member.new(self, index)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const\_set(symbol, member)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@members \<\< member  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;super(&block)  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def (index) @members[index] end  
> &nbsp;&nbsp;def size() @members.size end  
> &nbsp;&nbsp;alias :length :size
> 
> &nbsp;&nbsp;def first(\*args) @members.first(\*args) end  
> &nbsp;&nbsp;def last(\*args) @members.last(\*args) end
> 
> &nbsp;&nbsp;def each(&block) @members.each(&block) end  
> &nbsp;&nbsp;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  
&nbsp;&nbsp;&nbsp;Good = Struct::RatingData.new(:Good, 0.8, "Good Rating")  
&nbsp;&nbsp;&nbsp;Fair = Struct::RatingData.new(:Fair, 0.5, "Fair Rating")  
end

That seems more Rubyish to me.

---

<div class="post-metadata">

**Author:** ![Patrick\_Hurley1](https://avatars.discourse-cdn.com/v4/letter/p/b77776/32.png) [@Patrick\_Hurley1](https://rubytalk.org/u/Patrick_Hurley1)\
**Post date:** [28 August 2005 15:09 UTC](https://rubytalk.org/t/ruby-idiom-for-enum/20444/6 "2005-08-28T15:09:20Z")

</div>

Try this link:

[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/150439](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/150439)

See if it helps

pth

> **···**
>
> On 8/28/05, Brian Schröder \<ruby.brian@gmail.com\> wrote:
> 
> > On 28/08/05, David Brady \<ruby\_talk@shinybit.com\> wrote:  
> > \> Okay, one more question from a C++ leopard trying to change his spots:  
> > \>  
> > \> I want to set up a program that uses some predefined values to determine  
> > \> its logic. For example, a method could analyze some data and return  
> > \> "Good", "Fair", "Poor", or "Out of Bounds" based on a set of  
> > \> thresholds. I want to be able to refer to these values by name in my  
> > \> code, so constants or symbols make a good choice here. But I also want  
> > \> to build a sort of rule set around these values: some function returns  
> > \> values in the range of (0.0..1.0) and I want to be able to say that 0.8  
> > \> is the minimum score for "Good", etc. I also want the word "Good"  
> > \> stored in a specific single place so that I don't make any typos each  
> > \> time I need to print the description.  
> > \>  
> > \> 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.  
> > \>  
> > \> What's the Ruby idiom for this?  
> > \>
