From: Tim Hunter Date: 2003-08-13T20:46:32+09:00 Subject: Re: Exposing C "enums" through extensions On Wed, 13 Aug 2003 17:01:03 +0900, Brian Candler wrote: > On Wed, Aug 13, 2003 at 01:03:14PM +0900, Scott Thompson wrote: >> I'm allowing Ruby to access a C based library through an extension. I'd >> like to expose some of the enums that are in the C interface, but wasn't >> sure about the best way to do this. >> >> My first thought was to define them as class variables within the >> relevant class. But then, as I discovered, there wasn't a good way I >> could keep external code from modifying the values of those variables. >> It would be really bad if someone set the value of the "miter line join" >> constant to 7 when the only valid range of values is 0 - 3. > > The closest thing to enums would be class constants: > > class MyClass > THIN_LINE = 1 > THICK_LINE = 2 > MONSTER_LINE = 3 > end > > p MyClass::MONSTER_LINE > > (and being constants, you will at least get a warning if someone tries to > reassign them) > > Also, you don't have to expose variables in your classes, just provide > accessor methods (either instance methods or class methods) for settings > values; then you can validate the values yourself. > > class MyClass > def self.miter_line_join=(x) > raise "Naughty!" unless (0..3) === x > @@miter_line_join = x > end > end > > MyClass.miter_line_join = 3 > > Regards, > > Brian. This is the practice that RMagick follows. Each attribute accessor that accepts a constant has code that tests the input argument against the list of valid values. That, however, does not prevent somebody from assigning a constant with a correct value but incorrect name. For example, if APPLES = 3 then miter_line_join would happily accept APPLES as an argument. I don't regard this as a major problem.