你如何在 Ruby on Rails 中以编程方式找到命名空间/模块名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/133357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you find the namespace/module name programmatically in Ruby on Rails?
提问by Steropes
How do I find the name of the namespace or module 'Foo' in the filter below?
如何在下面的过滤器中找到命名空间或模块“Foo”的名称?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
回答by Jason Harrelson
None of these solutions consider a constant with multiple parent modules. For instance:
这些解决方案都没有考虑具有多个父模块的常量。例如:
A::B::C
As of Rails 3.2.x you can simply:
从 Rails 3.2.x 开始,您可以简单地:
"A::B::C".deconstantize #=> "A::B"
As of Rails 3.1.x you can:
从 Rails 3.1.x 开始,您可以:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
This is because #demodulize is the opposite of #deconstantize:
这是因为#demodulize 与#deconstantize 相反:
"A::B::C".demodulize #=> "C"
If you really need to do this manually, try this:
如果您确实需要手动执行此操作,请尝试以下操作:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
回答by Hettomei
For the simple case, You can use :
对于简单的情况,您可以使用:
self.class.parent
回答by Daniel Lucraft
This should do it:
这应该这样做:
def get_module_name
@module_name = self.class.to_s.split("::").first
end
回答by Steropes
This would work if the controller did have a module name, but would return the controller name if it did not.
如果控制器确实有模块名称,这将起作用,但如果没有,则会返回控制器名称。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
However, if we change this up a bit to:
但是,如果我们将其更改为:
class ApplicatioNController < ActionController::Base
def get_module_name
my_class_name = self.class.name
if my_class_name.index("::").nil? then
@module_name = nil
else
@module_name = my_class_name.split("::").first
end
end
end
You can determine if the class has a module name or not and return something else other than the class name that you can test for.
您可以确定该类是否具有模块名称,并返回您可以测试的类名称以外的其他内容。
回答by Dave Hollingworth
I know this is an old thread, but I just came across the need to have separate navigation depending on the namespace of the controller. The solution I came up with was this in my application layout:
我知道这是一个旧线程,但我刚遇到需要根据控制器的命名空间进行单独导航。我想出的解决方案是在我的应用程序布局中:
<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>
Which looks a bit complicated but basically does the following - it takes the controller class name, which would be for example "People" for a non-namespaced controller, and "Admin::Users" for a namespaced one. Using the [] string method with a regular expression that returns anything before two colons, or nil if there's nothing. It then changes that to lower case (the "try" is there in case there is no namespace and nil is returned). This then leaves us with either the namespace or nil. Then it simply renders the partial with or without the namespace, for example no namespace:
这看起来有点复杂,但基本上执行以下操作 - 它采用控制器类名称,例如,对于非命名空间控制器,它是“People”,对于命名空间控制器,它是“Admin::Users”。使用带有正则表达式的 [] 字符串方法,返回两个冒号之前的任何内容,如果没有,则返回 nil。然后将其更改为小写(如果没有命名空间并返回 nil,则存在“try”)。这给我们留下了命名空间或 nil。然后它简单地呈现带有或不带有名称空间的部分,例如没有名称空间:
app/views/_nav.html.erb
or in the admin namespace:
或在 admin 命名空间中:
app/views/admin/_nav.html.erb
Of course these partials have to exist for each namespace otherwise an error occurs. Now the navigation for each namespace will appear for every controller without having to change any controller or view.
当然,每个命名空间都必须存在这些部分,否则会发生错误。现在,每个命名空间的导航将出现在每个控制器上,而无需更改任何控制器或视图。
回答by sandstrom
my_class.name.underscore.split('/').slice(0..-2)
my_class.name.underscore.split('/').slice(0..-2)
or
或者
my_class.name.split('::').slice(0..-2)
my_class.name.split('::').slice(0..-2)
回答by Horacio
For Rails 6.1
对于 Rails 6.1
self.class.module_parent
self.class.module_parent
Hettomei answer works fine up to Rails 6.0
Hettomei 的答案在 Rails 6.0 之前都可以正常工作
DEPRECATION WARNING:
Module#parenthas been renamed tomodule_parent.parentis deprecated and will be removed in Rails 6.1.
弃用警告:
Module#parent已重命名为module_parent.parent已弃用,将在 Rails 6.1 中删除。
回答by Horacio
I don't think there is a cleanerway, and I've seen this somewhere else
我不认为有更干净的方法,我在其他地方看到过
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
回答by Pablo Cantero
I recommend gsubinstead of split. It's more effective that splitgiven that you don't need any other module name.
我推荐gsub而不是split. split鉴于您不需要任何其他模块名称,它更有效。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
回答by Cyril
With many sub-modules:
有许多子模块:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
Example: Foo::Bar::BazController=> Foo::Bar
例子:Foo::Bar::BazController=>Foo::Bar

