tags:

views:

53

answers:

2
class Foo
  def self.bar
    puts "foobar"
  end

  def bar
    self.class.bar
  end
end

I want to refrain from needing to define the instance method bar. Is there a way to automatically make class methods accessible as instance methods? Maybe with some method_missing? magic?

+1  A: 

Try something like:

class Foo

  def self.bar
    puts "foobar"
  end

  def respond_to? name
    super or self.class.respond_to? name
  end

  def method_missing name, *args, &block
    if self.class.respond_to? name
      self.class.send name, *args, &block
    else
      super
    end
  end

end

You can also do this (simple version):

module ChainsToClass
  def respond_to? name
    super or self.class.respond_to? name
  end
  def method_missing name, *args, &block
    if self.class.respond_to? name
      self.class.send name, *args, &block
    else
      super
    end
  end
end

class Foo
  def self.bar
    puts "foobar"
  end
end

Foo.send :include, ChainsToClass
Justice
Thanks! Although Ruby won't let you just call `class`, you have to use `self.class`.
Karl
Edited, thanks.
Justice
+1  A: 

The easiest way would be to define methods in a submodule and extend and include it into the class:

class Foo

  module FooMethods
    def bar
      puts "foobar"
    end
  end

  # Add methods from module FooMethods as class methods to class Foo
  extend FooMethods

  # Add methods from module FooMethods as instance methods to class Foo
  include FooMethods
end
Andreas
Good idea! I have some code that requires the class as the environment though, and I have the feeling using this method wouldn't handle things correctly in my case.
Karl
Inside the method, `self` holds either the class or the instance object, depending on wether you called the class method or the instance method. If you need to find out the class, you could add `def klass; self.is_a?(Class) ? self : self.class; end` to the module and access the class as `klass` instead of `self.class`.
Andreas