Ruby的根模块命名空间

如果你要定制Rails的违例输出页面的话的,一般会用这样的代码:
[code]
class ApplicationController < ActionController::Base
...
def rescue_action_in_public(exception)
case exception
when ::ActionController::UnknownAction
render_with_layout ....
when ActiveRecord::RecordNotFound
...
end
end
end[/code]

这里唯一奇怪的地方就是::ActionController::UnknownAction, 为什么去掉开头的::就会报错说找不到UnknownAction?看看源码,UnknownAction类确实存在于ActionController模块中啊。

简单说,Ruby的namespace是从当前位置开始的找起的,而由::开头访问的是所谓根模块命名空间(root module namespace),好比绝对路径。为了便于理解,我们来看个例子:
[code]
class Obj
def self.p
"Obj"
end
end
module Test
class Obj
def self.p
"Test::Obj"
end
end
class See
def self.p
puts Obj.p
puts ::Obj.p
end
end
end[/code]
在irb中load这段代码,并执行
[code]
>> Test::See.p
Test::Obj
Obj[/code]
显然See看见Obj会首先在同一命名域下搜索。而外层的Obj是和Test同级别的所谓根命名,使用::才能直接引用以区别于Test内部的Obj。另外如果这时在See.p里面插一句pp Module.constants就能看见根模块空间的内容。

好了,我们已经看见“绝对”和“相对”的区别。回到主题,为什么不能直接用ActionController::UnknownAction呢?这里涉及到Rails导入模块的一些“巫术”,使得当在Controller里用ActionController的时候指向的是
ActionWebService::Container::ActionController。所以要加个::让Ruby知道用的是根级的ActionController的。

可见这是个命名冲突的Rails bug, 框架应该对用户隐藏掉这种晦涩的东西。然而这个hack也不失为解决一般的命名冲突情况的办法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值