1

Do you know how to define @@method_names class variable so that both my_macro and invoke_methods can use it as intended? Thank you!

module MyModule

    module ClassMethods    
        def my_macro method_name, options = { }
            define_method method_name do
                puts "defining #{method_name} with #{options}"
            end
            @@method_names << method_name
        end    
    end

    def invoke_methods
        @@method_names.each { |method_name| send method_name }
    end

    def self.included includer
        includer.extend ClassMethods
    end

end

class MyClass
    include MyModule
    my_macro :method_foo, :bar => 5
    my_macro :method_baz, :wee => [3,4]
end

MyClass.new.invoke_methods
4
  • 1
    Maybe init first @@method_names = [] before @@method_names << method_name Commented Jun 23, 2011 at 19:35
  • I tried this: @@method_names = [] unless @@method_names; @@method_names << method_name but got NameError: uninitialized class variable @@method_names in MyModule::ClassMethods Commented Jun 23, 2011 at 19:40
  • Do this instead of using unless: @@method_names = @@method_names || [] Commented Jun 23, 2011 at 19:50
  • 1
    Thanks. Sure, more rubyish, but still gives the same error. Commented Jun 23, 2011 at 20:01

2 Answers 2

2

Here's a working version. Changes are commented:

module MyModule
    module ClassMethods
        @@method_names ||= [] #move this up here
        def my_macro method_name, options = { }
            define_method method_name do
                puts "defining #{method_name} with #{options}"
            end
            @@method_names << method_name
        end

        #added this (rename as required)
        def the_methods
          @@method_names
        end
    end

    def invoke_methods
        #changed this call
        self.class.the_methods.each { |method_name| send method_name }
    end

    def self.included includer
        includer.extend ClassMethods
    end
end

class MyClass
    include MyModule
    my_macro :method_foo, :bar => 5
    my_macro :method_baz, :wee => [3,4]
end

MyClass.new.invoke_methods
Sign up to request clarification or add additional context in comments.

Comments

1
module MyModule

    module ClassMethods    
        def my_macro method_name, options = { }
            define_method method_name do
                puts "defining #{method_name} with #{options}"
            end
            @method_names ||= []
            @method_names << method_name
        end  

        def method_names
          @method_names
        end  
    end

    def invoke_methods
        self.class.method_names.each { |method_name| send method_name }
    end

    def self.included includer
        includer.extend ClassMethods
    end

end

class MyClass
    include MyModule
    my_macro :method_foo, :bar => 5
    my_macro :method_baz, :wee => [3,4]
end

MyClass.new.invoke_methods

4 Comments

How to make it work with class variable instead of instance variable?
I don't think it is possible to access a class variable from a class method. @@var in a class method is a very weird thing, don't do it. In general using class variables is not recommended at all, even in "normal" case.
It is possible to access a class variable from a class method - not sure what you meant about that(class A; @@m = "hello"; def self.x; p @@m; end; end; A.x; ). But I agree with the rest of your statement.
@Zabba Originally "class" variable is @@v defined in the instance method, and such variable is shared between instances of the same class (and also inherited!) : class A; def a; @@a = 1 end; def b; puts @@a end; end; A.new.a; A.new.b. @@v defined in a class context is completely different beast. Why do you need it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.