Estoy usando class_eval
para escribir el código que se ejecutará en el contexto de la clase actual. En el siguiente código, quiero agregar un contador para los cambios de los valores de los atributos.¿Cuál es el alcance variable dentro de la cadena `class_eval`?
class Class
def attr_count(attr_name)
attr_name = attr_name.to_s
attr_reader attr_name # create the attribute's getter
class_eval %Q{
@count = 0
def #{attr_name}= (attr_name)
@attr_name = attr_name
@count += 1
end
def #{attr_name}
@attr_name
end
}
end
end
class Foo
attr_count :bar
end
f = Foo.new
f.bar = 1
Mi comprensión de class_eval
es que se evalúa el bloque en el contexto de la clase en tiempo de ejecución - en mi caso, bajo class Foo
. Espero que el código anterior se ejecuta similar a:
class Foo
attr_count :bar
@count = 0
def bar= (attr_name)
@attr_name = attr_name
@count += 1
end
def bar
@attr_name
end
end
Sin embargo el código anterior se tradujo en error diciendo, el error es causado por @count += 1
. No puedo entender por qué @count
tiene nil:NilClass
como su super?
(eval):5:in `bar=': undefined method `+' for nil:NilClass (NoMethodError)
Por otro lado, @selman ha dado una solución para poner @count
asignación dentro del método de instancia y funciona.
class Class
def attr_count(attr_name)
#...
class_eval %Q{
def #{attr_name}= (attr_name)
@attr_name = attr_name
if @count
@count += 1
else
@count = 1
end
end
#...
}
end
end
¿Por qué cambia el alcance variable? ¿Cómo ejecuta class_eval
su siguiente cadena?
¿Qué le pareció su clase CS169? :) –