I am getting "NoMethodError: undefined method `%' for nil:NilClass" for the following code block:
class Timer
attr_accessor :seconds
def initialize
@seconds = 0
end
def time_string
if seconds < 10
return "00:00:0" + seconds.to_s
elsif seconds < 60
return "00:00:" + seconds.to_s
elsif seconds < 540
minutes = seconds / 60
seconds %= 60
#seconds = seconds - (minutes * 60)
return "00:0" + minutes.to_s + ":0" + seconds.to_s
end
end
def timer
@timer
end
end
I know that 'seconds' is a Fixnum because I get NoMethod: Fixnum error when I try to #puts seconds without a #to_s. Also, the "/" operation on 'seconds' in the preceding line works fine. So why am I getting a NoMethod:nilclass error message?
Why am I even getting an error message? Shouldn't "%" work everywhere "/" does?
The following code works:
if seconds < 10
return "00:00:0" + seconds.to_s
elsif seconds < 60
return "00:00:" + seconds.to_s
elsif seconds < 540
minutes = @seconds / 60
seconds = @seconds % 60
return "00:0" + minutes.to_s + ":0" + seconds.to_s
end
It has something to do with instance variables, and my not understanding instance variables. would love to know how the nil got in there.
It's an interaction between methods called on self
, local variables, and Ruby's lack of syntactic distinction between those things.
If you change the line to this:
self.seconds %= 60
Then it works fine.
The problem is that when Ruby sees an assignment to an unqualified name, it creates a local variable with that name rather than looking for an accessor.
Here's a simple demonstration:
irb(main):001:0> def foo=(n)
irb(main):002:1> puts "Calling foo!"
irb(main):003:1> @foo=n
irb(main):004:1> end #=> nil
irb(main):005:0> foo=1 #=> 1
irb(main):006:0> @foo #=> nil
irb(main):007:0> self.foo=2
Calling foo!
=> 2
irb(main):008:0> @foo #=> 2