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 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
def print_path
puts path
end
private
def path
self.class.path
end
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:
class Repository
def self.path
@@path
end
class_method_proxy :path
def print_path
puts path
end
end
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.