Rails ActiveSupport::Concern 和方法评价
Rails ActiveSupport::Concern and method evaluation
我有这个应用程序,它使用 Devise 和 current_user
助手。当我创建一个模块时,current_user
在我提到它的属性后变为 nil
,即使它从未发生过。
class PagesController < ApplicationController
include ModuleTest
def index
a_test_method
end
end
和 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
输出:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> nil
然而,如果我delete/comment出这一行# current_user = nil if false
,current_user
仍然有效:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> #<User id: 1>
这是否与惰性求值有关?
编辑
整个问题取决于 Ruby 在不计算语句时如何定义变量:
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 >
这在底层是如何工作的?
current_user
是Devise提供的辅助方法,不是局部变量
没有名为 current_user=
的辅助方法。您可以通过将 current_user = nil
更改为 self.current_user = nil
并看到它崩溃来证明这一点。但这与你的问题无关。
所以结果是,您在 2 puts
之间定义了一个局部变量 current_user
,它隐藏了同名的辅助方法。
奇怪的是,虽然current_user = nil
因为if false
没有被执行,局部变量仍然被定义,并且它的值被隐式设置为nil
。这就是为什么您的第二个 puts
显示 nil
。即使您将 current_user = nil
更改为 current_user = :someone
,您的第二个 puts
仍应显示 nil
.
我有这个应用程序,它使用 Devise 和 current_user
助手。当我创建一个模块时,current_user
在我提到它的属性后变为 nil
,即使它从未发生过。
class PagesController < ApplicationController
include ModuleTest
def index
a_test_method
end
end
和 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
输出:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> nil
然而,如果我delete/comment出这一行# current_user = nil if false
,current_user
仍然有效:
(BEFORE)===========> #<User id: 1>
(AFTER) ===========> #<User id: 1>
这是否与惰性求值有关?
编辑
整个问题取决于 Ruby 在不计算语句时如何定义变量:
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 >
这在底层是如何工作的?
current_user
是Devise提供的辅助方法,不是局部变量没有名为
current_user=
的辅助方法。您可以通过将current_user = nil
更改为self.current_user = nil
并看到它崩溃来证明这一点。但这与你的问题无关。
所以结果是,您在 2 puts
之间定义了一个局部变量 current_user
,它隐藏了同名的辅助方法。
奇怪的是,虽然current_user = nil
因为if false
没有被执行,局部变量仍然被定义,并且它的值被隐式设置为nil
。这就是为什么您的第二个 puts
显示 nil
。即使您将 current_user = nil
更改为 current_user = :someone
,您的第二个 puts
仍应显示 nil
.