Ruby: Class Methods Proxy
Did you ever used class methods inside your instance methods? If yes, you probably noticed how frustrating can be to use the def print_path
puts path
end private
def path
self.class.path
end
end
self.class.my_class_method syntax. A solution could be to create a private method which encapsulates the class one.
class Repository
def self.path
@@path
end
In the above example, #print_path can print the @@code value, without worrying about it’s a class value, because we have wrapped it.
When I developed Sashimi I’ve widely used this technique, with a bad impact on the code duplication, and in order to DRY-up my code I extended the Ruby’s Class class in this way:
class Class
def class_method_proxy(*method_names)
method_names.each do |m|
self.class_eval %{
# Proxy method for #{self.class.name}##{m}
def #{m}(*args, &block)
self.class.#{m}(*args, &block)
end
private :#{m}
}, __FILE__, __LINE__
end
end
end
This approach allow us to annotate our classes, choosing which class methods should be available as private methods.
Now, our example class should look like the following: def print_path
puts path
end
end
class Repository
def self.path
@@path
end
class_method_proxy :path
Of course you can pass multiple symbols to proxy many methods at the same time.
class_method_proxy :path, :another_path, :a_third_one
UPDATE 2008-07-06: I added the &block argument.