This method increments the ActiveRecord attr_accessible attribute current_step:
def next_step
logger.debug "Now at step: " + current_step.inspect
if (current_step == nil)
current_step = 0
end
current_step = current_step + 1
end
At execution of the method, the log shows Now at step: 0 but the +1 line fails:
NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+):
app/models/assessment.rb:16:in `next_step'
Is it a miracle? Is current_step nil or not?
EDIT: Thanks fl00r and whitequark for the great answers! Here is what the code was meant to be:
def next_step
current_step ||= 0
self.current_step += 1
save
end
Conditionals and loops do not have their own scope in Ruby; and here you have a variable and a method of
selfwhich possess the same name. In the condition ofif, thecurrent_stepmethod is used, but in its body a local variable is defined, and all future references to thecurrent_stepwill refer to the local variable. The pitfall you’ve encountered is, even if theifbody is not executed, the local variable is still defined, and default value ofnilis assigned to it.I’ll make it more clear by adding
_Mto the identifier when the method is accessed, and_Lfor the local variable.I’m guessing you was actually trying to do
self.current_step = 0, which would invoke the setter.