Ruby: including class methods as if they were a module

Ruby’s File class has many public class methods named like their shell command counterparts, like chmod, chown, basename, stat, etc. These are very convenient when writing a shell script in Ruby, but typing “File.chown” isn’t as convenient as just “chown”. Now, if File were a module, I could include this module and I’d be done. Many file-related methods are available in the module FileUtil (third-party in Ruby 1.8, standard in Ruby 1.9) as well as FileTest. Methods like basename and stat are available in neither, so I thought a quick solution might be to also include File’s class methods. There doesn’t seem to be any straightforward way to do this, perhaps because File may be one of the few classes with so many static methods that don’t come from a module. So, a quick, dirty, Ruby metaprogramming solution:

def include_class_methods(klass)
  eval <<-EOF
    class << self
      klass = eval('#{klass.name}')
      klass.singleton_methods.each do |sym|
        define_method(sym) do |*args|
          klass.send sym, *args
        end
      end
    end
  EOF
end

Note: this doesn't seem to work in Ruby 1.9, as File.singleton_methods is empty. One possible replacement for File.singleton_methods is (File.public_methods - File.public_instance_methods - File.ancestors.reject { |x| x == File }.map { |x| x.methods }.flatten). Yeesh.

This entry was posted in Code. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>