如何在下面的过滤器中找到命名空间或模块“Foo”的名称?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
如何在下面的过滤器中找到命名空间或模块“Foo”的名称?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
这些解决方案都没有考虑具有多个父模块的常量。例如:
A::B::C
从 Rails 3.2.x 开始,您可以简单地:
"A::B::C".deconstantize #=> "A::B"
从 Rails 3.1.x 开始,您可以:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
这是因为#demodulize 与#deconstantize 相反:
"A::B::C".demodulize #=> "C"
如果您确实需要手动执行此操作,请尝试以下操作:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
对于简单的情况,您可以使用:
self.class.parent
这应该这样做:
def get_module_name
@module_name = self.class.to_s.split("::").first
end
self.class.module_parent
Hettomei 的答案在 Rails 6.0 之前都可以正常工作
弃用警告:
Module#parent
已重命名为module_parent
.parent
已弃用并将在 Rails 6.1 中删除。
如果控制器确实有模块名称,这将起作用,但如果没有,则返回控制器名称。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
但是,如果我们将其更改为:
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
您可以确定该类是否具有模块名称,并返回您可以测试的类名称以外的其他内容。
我知道这是一个旧线程,但我只是遇到了需要根据控制器的命名空间进行单独导航的需要。我想出的解决方案是在我的应用程序布局中:
<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>
这看起来有点复杂,但基本上执行以下操作 - 它采用控制器类名称,例如非命名空间控制器的“People”和命名空间控制器的“Admin::Users”。使用带有正则表达式的 [] 字符串方法,返回两个冒号之前的任何内容,如果没有任何内容,则返回 nil。然后它将其更改为小写(如果没有命名空间并返回 nil,则存在“try”)。然后,这给我们留下了命名空间或 nil。然后它只是简单地渲染有或没有命名空间的部分,例如没有命名空间:
app/views/_nav.html.erb
或在管理命名空间中:
app/views/admin/_nav.html.erb
当然,每个命名空间都必须存在这些部分,否则会发生错误。现在,每个控制器的每个命名空间的导航都将出现,而无需更改任何控制器或视图。
my_class.name.underscore.split('/').slice(0..-2)
或者
my_class.name.split('::').slice(0..-2)
没有人提到使用rpartition
?
const_name = 'A::B::C'
namespace, _sep, module_name = const_name.rpartition('::')
# or if you just need the namespace
namespace = const_name.rpartition('::').first
我认为没有更清洁的方法,我在其他地方看到过
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
我建议gsub
而不是split
. split
考虑到您不需要任何其他模块名称,它会更有效。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
有许多子模块:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
示例:Foo::Bar::BazController
=>Foo::Bar