you're close - the issue is that including a module in another class/module
only inserts the __instance__ methods of the included module into the
class/module doing the reciever. so, altough you've defined a class level
method correctly it doesn't make it into your new class. there are a couple of
ways around that - you can do things like:
module M
def foo; 42; end
end
class C
extend M
end
p C::foo #=> 42
but that only works if ALL the methods in M should be class methods - though
this is often the case where one is defining accessor type stuff in a module.
another approach is do define class level methods in the other class on the
fly and let the instance methods take care of themselves:
module M
def self::included other
class << other
def foo; 42; end
end
end
def bar; 'forty-two'; end
end
class C
include M
end
p C::foo #=> 42
c = C::new
p c.bar #=> 'forty-two'
what you can't do, however, is to define a class method in a module and then
somehow 'get it back' to inject it into the including class at runtime (well
you could but it'd be very ugly). i've found this approach to be quite simple
and almost guaranteed to make sense to any developer that ever programmed an
object-oriented language instantly - even if they don't understand the
included method totally:
harp:~ > cat b.rb
module JoeAccessors
module ClassMethods
def joe_accessor_method *args
args.each do |arg|
module_eval <<-src
def #{ arg }
@#{ arg }
end
def #{ arg }= value
@#{ arg } = value
end
src
end
end
end
module InstanceMethods
# put em here
end
def self::included other
other.extend ClassMethods
other.module_eval{ include InstanceMethods }
end
end
class Joe
include JoeAccessors
joe_accessor_method :arg1, :arg2
end
joe = Joe::new
joe.arg1 = 42
p joe.arg1
harp:~ > ruby b.rb
42
it's just a tiny bit clunky - but it makes it totally clear which methods are
which without any doccumentation or understanding of 'class << self' etc.
(note that you have to use 'module_eval' here.)
hth.
-a
···
On Tue, 16 Aug 2005, Joe Van Dyk wrote:
module JoeAccessors
class << self
def joe_accessor_method *args
args.each do |arg|
eval <<-src
def #{ arg }
@#{ arg }
end
def #{ arg }= value
@#{ arg } = value
end
src
end
end
end
end
class Joe
include JoeAccessors
joe_accessor_method :arg1, :arg2
end
test.rb:21: undefined method `joe_accessor_method' for Joe:Class (NoMethodError)
*bangs head against desk*
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================