Refinery stemmed from a very specific need that arose while writing
attr_* — to be able to utilize the Ruby hooks (for example, the
method_missing methods) without “gobbling them up” so to
speak. Normally, had I used those methods (especially if my particular
implementation was very dependent on these methods operating in a specific
way), the person using my library would be precluded from using the same
methods in whatever class they included/extended my library into; if they used
one of those methods for some purpose, their definition would ‘overwrite’ mine,
thus quite possibly making my library (or their code using my library) cease
to function correctly.
The simple, singular purpose of Refinery is to ‘refine’ methods in such a way that your important functionality can be assigned safely to these methods. Any attempts to re-define a ‘refined’ method after the refining process will simply ‘stack’ with your own implementation — your method code will execute first, with further re-definitions each being executed in turn when the method is called.
Using Refinery is very simple - extend it into your class (or include it into the Class class if you use it often), and then pass a method's name (as a symbol) to the refine_method singleton method. A short example:
class Something extend Refinery def method_missing meth, *args # Do some magic! puts 'abc' end refine_method :method_missing end # Later, somewhere else… class Nothing < Something def method_missing meth, *args # Do other magic, not knowing about the former magic! puts 'def' end end nothing = Nothing.new nothing.nonexistant_method
Once refined, any further re-openings of your class (or a descendant) and re-definitions of the refined method will simply result in the implementations 'stacking' with eachother.
Care must obviously still be taken to ensure your code will 'stack' in a friendly way with the other implementations — be sure to programmatically check whatever may be necessary before executing your method's code!
You can install Refinery as a pre-built gem, or as a gem generated directly from the source.
sudo gem install refinery # You'll be asked for your account password.
Alternatively, you can acquire it (possibly slightly more up-to-date, depending on how often I update the gemspec) from GitHub as follows:
# If you've ever done this before, you don't need to do it now - see http://gems.github.com gem sources -a http://gems.github.com sudo gem install elliottcable-refinery # You'll be asked for your account password.
Finally, you can build a gem from the latest source yourself. You need git, as well as [rake]:
git clone git://github.com/elliottcable/refinery.git cd refinery # If you've ever done this before, you don't need to do it now - see http://gems.github.com gem sources -a http://gems.github.com sudo gem install elliottcable-echoe # You'll be asked for your account password. rake install # You'll be asked for your account password.
You can contribute bug fixes or new features to Refinery by forking the project on GitHub (you'll need to register for an account first), and sending me a pull request once you've committed your changes.
- GitHub is the project's primary repository host, and currently also the project's home page
- RubyForge is out primary RubyGem host, as well as an alternative repository host
- integrity is out continuous integration server - if the top build on that page is green, you can assume the latest git HEAD is safe to run/install/utilize.
- Gitorious is an alternative repository host
- repo.or.cz is an alternative repository host
The Sing extension was contributed by John Mair.
Refinery is copyright 2008 by elliott cable.
Refinery is released under the GNU General Public License v3.0, which allows you to freely utilize, modify, and distribute all Refinery's source code (subject to the terms of the aforementioned license).