views:

32

answers:

1

I have a question about best practices for Ruby variable scope using class_eval.

In the below code snippet, in the class_eval block, the local variables first and second are undefined.

def parent_method(opts={})
    first = opts[:percent]
    second = (10 * first).to_i

    SecondClass.class_eval do 
      def second_method; return {:a => first, :b => second}; end; 
    end     
end

This appears to be a scoping issue, because the only way I've found to get this to work is to make first and second class-level variables, as in the below.

def parent_method(opts={})
    @@first = opts[:percent]
    @@second = (10 * @@first).to_i

    SecondClass.class_eval do 
      def second_method; return {:a => @@first, :b => @@second}; end; 
    end     
end

My question is:

(1) what is the best practice for this scenario? I realize globals are a poor choice for this scenario, because of the wide scope that results, however, are class-level variables similarly frowned upon?

(2) aside from dealing with variable scope, are there any other ways to address the accessibility of these variables from within class_eval?

Thanks!

+2  A: 

The problem is not because of class_eval, but because of def. When you define a method that way, it introduces a new scope. Here is the best way to fix it:

def parent_method(opts={})
    first = opts[:percent]
    second = (10 * first).to_i

    SecondClass.class_eval do 
      define_method(:second_method) { return {:a => first, :b => second} }
    end     
end
Adrian
Great! Thank you - this works!
shedd