1

I wrote the following code. When I run Hello.run I want to log a message, but this does not work.

Why does not this work?

class Hello
  def initialize
    @logger = Logger.new STDOUT
  end

  def self.run
    self.new
    @logger.warn 'Hello'
  end
end

Hello.run

This is the error message I get when running Hello.run

NoMethodError: private method `warn' called for nil:NilClass
pkhamre
  • 371
  • 1
  • 16

2 Answers2

2

The @logger variable you set in the constructor is an instance variable, and self.run is a class method.

Instance variables are not available in class methods, so when you're running Hello.run, you won't be able to access the Hello class' internal instance variable.

If you want the logger to be class wide, you could define it as a class variable, like so:

class Hello
  def initialize
    @@logger ||= Logger.new(STDOUT)
  end

  def self.run
    self.new # I don't get why you just create a new instance and throw it away
    @@logger.warn("Hello")
  end
end

I have a longer answer on different variable scopes here, if you are interested.

Community
  • 1
  • 1
Frost
  • 11,121
  • 3
  • 37
  • 44
  • Thanks, I will read your longer answer too. Seems like I just need a better understanding of Ruby classes, and variable scopes. – pkhamre Jul 18 '12 at 12:48
0

You have to create a new object of your class. When you do this initialize will be called.

Otherwise @logger won't be initialized.

hello = Hello.new
hello.run
lukad
  • 17,287
  • 3
  • 36
  • 53
  • 1
    Since the `run` method is a class method, your example won't work. `def self.method_name` in ruby is called by `ClassName.method_name`. – Frost Jul 18 '12 at 13:05