Search code examples
ruby-on-railsrubyblock

Ruby struct creation block cannot access variable outside the block


Accessing the default variable inside the Struct creation block doesn't seem to work in this case:

default = 'test'
A = Struct.new(:a, :b) do
  def initialize(*args)
    super(*args)
    self.b ||= default
  end
end

It is throwing the following error:

'initialize': undefined local variable or method `default' for #<struct A a=2, b=nil> (NameError)

Can someone explain why this is happening and whether there is a work around?

(Tested on Ruby 1.9.3 and 2.1.2)


Solution

  • It's because def keyword starts new local variables scope, so default local variable isn't visible inside of it. The workaround is to use define_method, because the block you pass into it is closure:

    default = 'test'
    A = Struct.new(:a, :b) do
      define_method(:initialize) do |*args|
        super(*args)
        self.b ||= default
      end
    end
    a = A.new
    a.b
    # => "test"