In Ruby, suppose I have a class Foo to allow me to catalogue my large collection of Foos. It's a fundamental law of nature that all Foos are green and spherical, so I have defined class methods as follows:
class Foo
def self.colour
"green"
end
def self.is_spherical?
true
end
end
This lets me do
Foo.colour # "green"
but not
my_foo = Foo.new
my_foo.colour # Error!
despite the fact that my_foo is plainly green.
Obviously, I could define an instance method colour which calls self.class.colour, but that gets unwieldy if I have many such fundamental characteristics.
I can also presumably do it by defining method_missing to try the class for any missing methods, but I'm unclear whether this is something I should be doing or an ugly hack, or how to do it safely (especially as I'm actually under ActiveRecord in Rails, which I understand does some Clever Fun Stuff with method_missing).
What would you recommend?
You could define a passthrough facility:
module Passthrough
def passthrough(*methods)
methods.each do |method|
## make sure the argument is the right type.
raise ArgumentError if ! method.is_a?(Symbol)
method_str = method.to_s
self.class_eval("def #{method_str}(*args) ; self.class.#{method_str}(*args) ; end")
end
end
end
class Foo
extend Passthrough
def self::colour ; "green" ; end
def self::is_spherical? ; true ; end
passthrough :colour, :is_spherical?
end
f = Foo.new
puts(f.colour)
puts(Foo.colour)
I don't generally like using eval, but it should be pretty safe, here.