I have the following code:
class MyXmlReader
attr_accessor :filename, :lines
def initialize(filename)
@filename = filename
@line_hash = {}
end
def read
reader = Nokogiri::XML::Reader(open(@filename))
Xml::Parser.new(reader) do
... do stuff
@line_hash[var] = line # ERROR!
end
end
end
It looks like the block runs in a new scope. Because I'm getting:
NoMethodError: undefined method `[]' for nil:NilClass
This is easily worked around by creating local variables and then assigning those variables to the instance variables at the end of the read method. But I'm wondering why a local variable is accessible within the block, but not an instance variable.
The interesting question isn't so much why the local variable is accessible inside the block (of course it is, blocks are closures, having access to local variables from the surrounding scope is kind of the point), but rather why the instance variable isn't. Because, actually, it should be accessible.
However, if the block is being instance_evaled or instance_execed, then the value of self will be changed to the receiver of the instance_eval or instance_exec message, and instance variables are always looked up in self, so since self is now a different object, it probably won't have an @line_hash instance variable. You would have to look at the implementation of Xml::Parser::new to find out.
See also How does instance_eval work and why does DHH hate it?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With