Reputation: 135
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?
Upvotes: 2
Views: 357
Reputation: 8888
current_user
is a helper method provided by Devise, not a local variable.
There is no such helper method named current_user=
. You can prove this by changing current_user = nil
to self.current_user = nil
and see it crash. But this is irrelevant to your issue.
So the result is, you defined a local variable current_user
between the 2 puts
, which shadows the helper method with the same name.
The weird thing is, although current_user = nil
is not executed because of the if false
, the local variable still gets defined, and its value is implicitly set to nil
. This is why your second puts
shows nil
. Even if you change your current_user = nil
to current_user = :someone
, your second puts
should still show nil
.
Upvotes: 2