I have this application which uses Devise with current_user helper. When I create a module, current_user becomes nil after I mention an attribution to it even though it never happens.
class PagesController < ApplicationController
include ModuleTest
def index
a_test_method
end
end
And the ModuleTest:
module ModuleTest
extend ActiveSupport::Concern
def a_test_method
puts "(BEFORE)===========> #{current_user.inspect}"
current_user = nil if false
puts "(AFTER) ===========> #{current_user.inspect}"
end
end
Output:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> nil
However, if I delete/comment out this line # current_user = nil if false, current_user remains valid:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> #<User id: 1>
Would this be related to lazy evaluation somewhat?
EDIT
The whole problem relies on how Ruby defines variables when a statement is not evaluated:
2.3.4 (main):0 > defined? this_never_seen_variable_before
=> nil
2.3.4 (main):0 > this_never_seen_variable_before = "value" if false
=> nil
2.3.4 (main):0 > defined? this_never_seen_variable_before
=> "local-variable"
2.3.4 (main):0 >
2.3.4 (main):0 > this_never_seen_variable_before_2
NameError: undefined local variable or method `this_never_seen_variable_before_2' for main:Object
from (pry):119:in `<main>'
2.3.4 (main):0 > this_never_seen_variable_before_2 = "value" if false
=> nil
2.3.4 (main):0 > this_never_seen_variable_before_2
=> nil
2.3.4 (main):0 >
How does this work underneath?
current_useris a helper method provided by Devise, not a local variable.There is no such helper method named
current_user=. You can prove this by changingcurrent_user = niltoself.current_user = niland see it crash. But this is irrelevant to your issue.So the result is, you defined a local variable
current_userbetween the 2puts, which shadows the helper method with the same name.The weird thing is, although
current_user = nilis not executed because of theif false, the local variable still gets defined, and its value is implicitly set tonil. This is why your secondputsshowsnil. Even if you change yourcurrent_user = niltocurrent_user = :someone, your secondputsshould still shownil.