DRYing/Cleaning Up Your Code/Namespaces With 'using'
There are times when I need a certain calculated object multiple times to compose other objects, but don't want to pollute my local namespace with unnecessary variables names. Consider building string paths in Merb:
aasm_location = Merb.root / ".." / "vendor" / "plugins" / "acts_as_state_machine"
$:.unshift(aasm_location / "lib") unless $:.include?(aasm_location / "lib")
require aasm_location / "init"
The "problem" is now there's a variable named aasm_location in my local scope, when there doesn't need to be. So... I've defined the following system-wide helper method:
class Object
def using(*args)
yield(*args) if block_given?
end
end
Yes, it's generally bad mojo to drop new method definitions in Object, that magical being from which all things descend, but I really wanted it available from everywhere. Now the first block of code can look like this:
using Merb.root / ".." / "vendor" / "plugins" / "acts_as_state_machine" do |aasm_location|
$:.unshift(aasm_location / "lib") unless $:.include?(aasm_location / "lib")
require aasm_location / "init"
end
or, if you're a glutton for punishment:
using Merb.root / ".." / "vendor" / "plugins" / "acts_as_state_machine" do |aasm_location|
using(aasm_location / "lib"){ |lib_loc| $:.unshift(lib_loc) unless $:.include?(lib_loc) }
require aasm_location / "init"
end
As soon as the blocks end, aasm_location and lib_loc go out of scope, preventing them from littering the rest of my current namespace.
Edit: After being made fun of by wycats in #merb, I changed the name from using to abusing.