Renum -- a Ruby enum gem
A while back I blogged through trying to implement something in Ruby similar to what you get from Java and C#'s enum keyword (and before there was a keyword, from the type-safe enumeration pattern in Java). It went pretty well.
I mentioned there that I might go ahead and package the thing (or something like it) up as a gem. Tonight I did. It's called Renum.
Renum lets you create enums like this:
enum :Status, [ :NOT_STARTED, :IN_PROGRESS, :COMPLETE ]
enum :Color, [ :RED, :GREEN, :BLUE ] do
name[0..0]
end
end
As of version 0.0.1, released just minutes ago, those enums work like this:
describe "enum" do
it "creates a class for the value type" do
Status.class.should == Class
end
it "makes each value an instance of the value type" do
Status::NOT_STARTED.class.should == Status
end
it "exposes array of values" do
Status.values.should == [Status::NOT_STARTED, Status::IN_PROGRESS, Status::COMPLETE]
end
it "enumerates over values" do
Status.map {|s| s.name}.should == %w[NOT_STARTED IN_PROGRESS COMPLETE]
end
it "indexes values" do
Status[2].should == Status::COMPLETE
Color[0].should == Color::RED
end
it "provides index lookup on values" do
Status::IN_PROGRESS.index.should == 1
Color::GREEN.index.should == 1
end
it "allows an associated block to define instance methods" do
Color::RED.abbr.should == "R"
end
it "provides a reasonable to_s for values" do
Status::NOT_STARTED.to_s.should == "Status::NOT_STARTED"
end
end
Hopefully someone will find this useful. There are some obvious features to add, like value lookup by name. There are also a lot of things that could be locked down a little, but the library's useful without that so I'm not sure it's worthwhile. (For example, I don't currently prevent you calling Color.new 'HAZEL'
.)
If this is something you might use, let me know what you want out of it.
Also, tonight I arrived in Charlotte for RubyConf. Say hi if you see me.
6 comments:
Nice gem! However, I have a question about how the usage with the block works. With a Java enum, it's possible to define different behavior for each enumerated value - for example, your "abbr" method could have a different implementation for each constant. Does renum have a way to do that without a switch in the defined method?
That's not supported yet, but it ought to be. I'll put that on my todo list for the holiday break. Thanks.
thanks for moving ruby forward
I've made a similar library available called Enumeration:
Colors = Enumeration.of :red, :blue, :green
http://github.com/karlin/enumeration/tree/master
Note that as of a few days ago Renum now lives at github: http://github.com/duelinmarkers/renum.
You might like the enumerated_attribute gem on github: http://github.com/jeffp/enumerated_attribute/tree/master.
It works like this:
enum_attr :mode, %w(off sleeping hibernating running)
Post a Comment