Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access an instance variable inside of a Ruby block? [duplicate]

Tags:

ruby

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.

like image 592
AKWF Avatar asked Oct 27 '25 06:10

AKWF


1 Answers

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?

like image 121
Jörg W Mittag Avatar answered Oct 28 '25 20:10

Jörg W Mittag



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!