Reputation: 18804
Why am I not able to access the variable vehicle
inside the class_eval
block:
class Vehicle
def self.number_of_wheels
fail 'DEFINE in subclass'
end
def self.name
fail 'DEFINE in subclass'
end
def self.define_methods
number_of_wheels.times do |index|
define_method("wheel_#{index}") do
"This is wheel #{index} of #{self.class.name}"
end
end
end
end
klasses = %w(
tri_cycle
motor_boat
).map do |vehicle| # THE VARIABLE I WANT TO ACCESS
klass = Class.new(Vehicle)
klass.class_eval do
def self.number_of_wheels
4
end
def self.name
vehicle # using a string here will work
end
define_methods
end
klass
end
klasses.map { |k| k.new.wheel_1 } # =>
# ~> -:31:in `name': undefined local variable or method `vehicle' for #<Class:0x007ff6ea181800> (NameError)
# ~> from -:13:in `block (2 levels) in define_methods'
# ~> from -:40:in `block in <main>'
# ~> from -:40:in `map'
# ~> from -:40:in `<main>'
Upvotes: 1
Views: 675
Reputation: 230286
It's so called "scope gate". Local variables go out of scope as soon as definition of method, class or module begins. See this book for more in-depth info: https://pragprog.com/book/ppmetr2/metaprogramming-ruby-2
You can bypass this by using define_method
or define_singleton_method
(whatever is suitable to you) instead of def
syntax (because this would be a method call, not method definition)
Upvotes: 3