I have a class with some methods. It’s supersekret but I’ve reproduced what I can here.
Class RayGun # flashes red light # requires confirmation # makes 'zowowowowowow' sound def stun! # ... end # flashes blue light # does not require confirmation # makes 'trrrtrtrtrrtrtrtrtrtrtr' sound def freeze! # ... end # doesn't flash any lights # does not require confirmation # makes Windows startup sound def killoblast! # ... end end
I want to be able to, at runtime, interrogate the class about one of the methods and receive a hash or struct like so:
{:lights => 'red', :confirmation => false, :sound => 'windows'}
What’s the best way of doing this? Obviously you could have separate YAML file alongside and set up a convention to relate the two, but ideally I want code and metadata in one place.
The most promising idea I can come up with is something like this:
class RayGun cattr_accessor :metadata def self.register_method(hsh) define_method(hsh.name, hsh.block) metadata[hsh[:name]] = hsh end register_method({ :name => 'stun!', :lights => 'red', :confirmation => 'true', :sound => 'zowowo', :block => Proc.new do # code goes here }) # etc. end
Anyone got some better ideas? Am I barking up a very wrong tree?
I found another strategy poking around http://github.com/wycats/thor/tree. Thor lets you write stuff like this:
It manages this by using the (undocumented) hook
Module#method_added. It works like this:Call to
Thor#descandThor#method_optionsset instance variables@desc,@method_options.Defining method
stun!callsThor#method_added(meth)Thor#method_addedregistersTask.new(meth.to_s, @desc, @method_options)(roughly speaking) and unsets@desc,@method_options.It’s now ready for the next method
Neat! So neat that I am going to accept my own answer 🙂