views:

56

answers:

1

I'm trying to figure why this code:

class BaseClass
end

module Extensions
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def message(message)
      @@message = message
    end
  end
end

BaseClass.send(:include, Extensions)

class ExtendedClass < BaseClass
  message "hello world!"

  def say_message
    puts @@message
  end
end

ExtendedClass.new.say_message

outputs:

test.rb:22:in `say_message': uninitialized class variable @@message in ExtendedClass (NameError)
    from test.rb:26:in `<main>'

instead of

hello world!

Can you please explain me why?

+2  A: 

Because when this method is executed:

def message(message)
  @@message = message
end

@@message refers to a class variable in the module ClassMethods (not the class ExtendedClass)

Here's a one line change that makes it work the way you expect:

def message(message)
  self.send(:class_variable_set, "@@message", message)
end

This is a bit of an antipattern (using 'send' to bypass the fact that 'class_variable_set' is private) but I believe it answers the question.

HTH

Blake Miller