我有以下代码来拉出并实例化Rails控制器:
def get_controller(route)
name = route.requirements[:controller]
return if name.nil?
if name.match(/\//)
controller_name = name.split('/').map(&:camelize).join('::')
else
controller_name = name.camelize
end
p controller_name: controller_name
controller = Object.const_get("#{controller_name}Controller")
p controller: controller
controller.new
end
有些路线是单一名称 - &#34;用户&#34;,&#34;朋友&#34;,&#34;邻居&#34;,&#34;政客&#34;等... < / p>
其他路线是嵌套的,例如&#34; admin / pets&#34;,&#34; admin / shopping_lists&#34;,&#34; admin / users&#34;等...
在上面提到的大多数情况下,上面的代码都有效(因为它可以正确地构建和实例化控制器),除了一个 - 在这个例子中,&#34; admin / users&#34;
来自puts
语句,我得到以下内容:
{:controller_name=>"Admin::Users"}
{:controller => UsersController}
您会注意到名称空间Admin
正在被切断。我的猜测是,因为这只是在多个名称空间(users
和admin/users
)中共享名称的控制器的情况,所以它与Rails自动加载(?)有关。有什么原因造成的?
根据lx00st的评论,我还应该指出,我已经尝试了各种形式的获取这些常量,另一种尝试如下:
sections = name.split('/')
sections.map(&:camelize).inject(Object) do |obj, const|
const += "Controller" if const == sections.last
obj.const_get(const)
end
这种方法遇到了同样的问题。
答案 0 :(得分:3)
这是通过用户apneadiving的答案解决的,可以找到here
请注意Rails开发模式中存在恶意案例。为了获得速度,加载严格的最小值。然后Rails在需要时查找类定义。
但是,当您说
::User
已经加载,然后查找::Admin::User
时,这有时会失败。 Rails不会寻找它,它会认为::User
可以解决问题。这可以使用代码中的
require_dependency
语句来解决。
我个人认为这是一个错误,不是一个功能,但是......所以它就是这样。它解决了这个问题。
答案 1 :(得分:1)
首先,这段代码是多余的:
if name.match(/\//)
controller_name = name.split('/').map(&:camelize).join('::')
else
controller_name = name.camelize
end
唯一的字符串可以完美地处理两种情况:
controller_name = name.split('/').map(&:camelize).join('::')
然后,您可能希望正确处理命名空间:
n_k = controller_name.split('::')
klazz = n_k.last
namespace_object = if n_k.length == 1
Object
else
Kernel.const_get(n_k[0..-2].join('::'))
end
controller = namespace_object.const_get("#{klazz}Controller")
希望有所帮助。