ruby 从命名空间字符串推导控制器名称

eulz3vhy  于 2023-03-08  发布在  Ruby
关注(0)|答案(1)|浏览(104)

在我的Rails代码库中,我使用了以下代码:

Rails.application.routes.recognize_path(request.referer)

我的目标是获取:controller键的class对象,到目前为止,我只得到了如下内容:my/namespace/posts.
然而真正的类是My::Namespace::PostsController。有没有办法自动推导出类名?否则,什么不是最优雅的方法?

wn9m85ua

wn9m85ua1#

@zakariah提到了ActionDispatch::Request#controller_class,如果params[:controller]String,它应该可以工作,尽管我还没有测试过它:

params = {controller: '/my/namespace/posts'}
ActionDispatch::Request.new({}).controller_class_for(params[:controller])
#=> My::Namespace::PostsController
request.controller_class # in theory 
#=> My::Namespace::PostsController

然而,如果控制器不存在,则这将产生错误。
也就是说,基于当前的实现,您已经成功地获得了String "my/namespace/posts",这意味着您已经完成了90%的工作。
将其转换为所需的控制器名称实际上相当简单:

str = "my/namespace/posts" 
controller_name = str.camelize << "Controller" 
#=> "::My::Namespace::PostsContoller"
contoller_name.safe_constantize
#=> ::My::Namespace::PostsContoller

这是AbstractController::Base#controller_path的简单反转,它使用underscore
如文件所述:
ActiveSupport::Inflector::camelize
[camelize]还将"/"转换为"::",这对于将路径转换为命名空间非常有用....

    • 重要说明**:

...作为一个经验法则,您可以将camelize视为underscore的逆,尽管在某些情况下这并不成立:
camelize(underscore('SSLError')) # => "SslError"
因此,如果应用程序中需要,您需要确保设置正确的变形。
我选择使用safe_constantize,如果常量不存在,它将返回nil。这允许您以更惯用的方式处理这些问题(缺少常量)。

controller_name.safe_constantize || DefaultContoller

相关问题