This post originated from an RSS feed registered with Ruby Buzz
by john hume.
Original Post: Renum 1.1: pretty instance-specific method definition
Feed Title: El Humidor
Feed URL: http://feeds.feedburner.com/ElHumidor
Feed Description: John D. Hume on Ruby and development with agile teams.
You could always define instance-specific behavior on Renum values the same way you can on any object in Ruby:
enum :FakeWorddo
Foo()Bar()Baz()defextra_stuff"no extra stuff here"endenddefFoo.extra_stuff"here's the foo stuff"end
That works fine, but it's a little ugly.
Starting this afternoon (with release 1.1) you can do this instead:
enum :FakeWorddo
Foodo
defextra_stuff"here's the foo stuff"endendBar()Baz()defextra_stuff"no extra stuff here"endend
FakeWord::Foo will have its own implementation of extra_stuff while FakeWord::Bar and FakeWord::Baz will have the one defined inside the enum block. This was implemented by just instance_eval'ing the given block against the instance just after creating it. A def form in an instance_eval'd block ends up defining a singleton method, so it's equivalent to the uglier version above.
This ends up looking almost exactly like the Java enum equivalent for defining constant-specific class bodies.
Since the block is instance_eval'd, if you prefered you could do any initialization there instead of defining an init method. Depending on what you've got going on it may turn out to be more readable. Here's a contrived example from the spec translated to that style.
# init-with-args-style
enum :Sizedo
Small("Really really tiny")Medium("Sort of in the middle")Large("Quite big")attr_reader:descriptiondefinitdescription@description= description
endend
# instance-block-per-value-style
enum :Sizedo
Small{@description="Really really tiny"}Medium{@description="Sort of in the middle"}Large{@description="Quite big"}attr_reader:descriptionend
The latter is probably slightly easier to digest, but it's also an extremely simple case, so I'd expect your mileage to vary quite a bit. (Note that you can do both an init with arguments AND an associated block. Renum evals the block before calling init, so any instance-specific behavior is in place before your init runs.)
Anyway, comment, suggest, complain, fork, improve, and enjoy.