这是一个简单的解决方案。
变化:
- 无需检查
USER_KEY 是否存在。
- 尝试在接收器的模块/类上查找常量(在您的情况下,它将是控制器)。如果存在,请使用它,否则使用默认模块/类(请参阅下面的默认模块/类)。
.
module Auth
USER_KEY = "user"
def authorize
user_key = self.class.const_defined?(:USER_KEY) ? self.class::USER_KEY : USER_KEY
user_id = session[user_key]
def
end
说明
您看到的行为不是特定于 rails 的,而是由于 ruby 在没有通过 :: 明确限定范围的情况下查找常量(我在上面称之为“默认”)。使用“当前执行代码的词法范围”查找常量。这意味着 ruby 首先在执行代码的模块(或类)中查找常量,然后向外移动到每个连续的封闭模块(或类),直到找到在该范围内定义的常量。
在您的控制器中,您调用authorize。但是当authorize在执行时,当前正在执行的代码在Auth中。这就是查找常量的地方。如果 Auth 没有USER_KEY,但一个封闭模块有它,那么将使用封闭模块。示例:
module Outer
USER_KEY = 'outer_key'
module Auth
# code here can access USER_KEY without specifying "Outer::"
# ...
end
end
这种情况的一个特例是顶级执行环境,它被视为属于类Object。
USER_KEY = 'top-level-key'
module Auth
# code here can access the top-level USER_KEY (which is actually Object::USER_KEY)
# ...
end
一个缺陷是使用作用域运算符 (::) 定义模块或类:
module Outer
USER_KEY = 'outer_key'
end
module Outer::Auth
# methods here won't be able to use USER_KEY,
# because Outer isn't lexically enclosing Auth.
# ...
end
请注意,常量的定义可以比方法的定义晚得多。仅在访问 USER_KEY 时才会进行查找,所以这也有效:
module Auth
# don't define USER_KEY yet
# ...
end
# you can't call authorize here or you'll get an uninitialized constant error
Auth::USER_KEY = 'user'
# now you can call authorize.