Why does the instance_variables
method not show @var_one
against the variable a
?
a = Object.new
def a.my_eval; yield end
a.my_eval { @var_one = 1 }
a.instance_variables
# => []
instance_variables
# => [@var_one]
Why does the instance_variables
method not show @var_one
against the variable a
?
a = Object.new
def a.my_eval; yield end
a.my_eval { @var_one = 1 }
a.instance_variables
# => []
instance_variables
# => [@var_one]
You should use instance_eval
:
a.instance_eval { @var_one = 1 }
=> 1
a.instance_variables
=> [:@var_one]
When you use ordinary eval
, you define your instance variable in context of current self
, if you do it in irb, it is the main
object:
a.eval { self }
=> main
So, you can modify your a.eval
method by executing a block in a context of an instance:
def a.eval(&block)
instance_eval &block
end
a.eval { @a = 1 }
=> 1
a.instance_variables
=> [:@a]
If your goal is to set an instance variable programmatically, you can use:
a.instance_variable_set(:@var_one, 1)
You should know the difference between eval
and instance eval
:
Kernel.eval
evaluates a string in the current context or the context of the given binding. It is the method used by IRB to process your input. It allows you to define new variables and methods for the current context.
Object.instance_eval
evaluates a string (or the given block) within the context of a certain class instance and allows thus the direct access to class properties without attr
or attr_accessor
. It allows you to define new methods for a instance.
So :
a.instance_eval { @var_one = 1 }
a.instance_variables
# => [:@var_one]
© 2022 - 2024 — McMap. All rights reserved.
eval
, so is not usingKernel.eval
. I think the answer is more directly to do with the block's binding and howyield
orProc#call
interacts with that binding. – Wallacewallach