如何在Ruby on Rails中以编程方式找到名称空间/模块名称?

时间:2022-09-28 14:06:07

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

9 个解决方案

#1


88  

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是# deconstanze的反义词:

"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]

#2


20  

This should do it:

这应该这样做:

  def get_module_name
    @module_name = self.class.to_s.split("::").first
  end

#3


14  

For the simple case, You can use :

对于简单的情况,您可以使用:

self.class.parent

#4


6  

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.

您可以确定类是否有模块名,并返回除可以测试的类名之外的其他内容。

#5


2  

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”表示有名称空间的控制器。使用带有正则表达式的[]string方法,该表达式在两个冒号之前返回任何内容,如果没有的话返回nil。然后将其更改为小写(如果没有名称空间和返回nil,则“try”在那里)。这就给我们留下了命名空间或nil。然后,它只会呈现出带有或没有名称空间的部分,例如没有名称空间:

app/views/_nav.html.erb

or in the admin namespace:

或者在管理名称空间中:

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.

当然,对于每个命名空间,这些偏置必须存在,否则会发生错误。现在,每个名称空间的导航将出现在每个控制器上,而不必更改任何控制器或视图。

#6


2  

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)

#7


1  

I don't think there is a cleaner way, and I've seen this somewhere else

我不认为有更干净的方法,我在别的地方见过

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.name.split("::").first
  end
end

#8


1  

I recommend gsub instead of split. It's more effective that split given that you don't need any other module name.

我推荐gsub而不是split。考虑到您不需要任何其他模块名,分割更有效。

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.to_s.gsub(/::.*/, '')
  end
end

#9


1  

With many sub-modules:

有很多子模块:

module ApplicationHelper
  def namespace
    controller.class.name.gsub(/(::)?\w+Controller$/, '')
  end
end

Example: Foo::Bar::BazController => Foo::Bar

例子:Foo:酒吧:BazController Foo = >::酒吧

#1


88  

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是# deconstanze的反义词:

"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]

#2


20  

This should do it:

这应该这样做:

  def get_module_name
    @module_name = self.class.to_s.split("::").first
  end

#3


14  

For the simple case, You can use :

对于简单的情况,您可以使用:

self.class.parent

#4


6  

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.

您可以确定类是否有模块名,并返回除可以测试的类名之外的其他内容。

#5


2  

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”表示有名称空间的控制器。使用带有正则表达式的[]string方法,该表达式在两个冒号之前返回任何内容,如果没有的话返回nil。然后将其更改为小写(如果没有名称空间和返回nil,则“try”在那里)。这就给我们留下了命名空间或nil。然后,它只会呈现出带有或没有名称空间的部分,例如没有名称空间:

app/views/_nav.html.erb

or in the admin namespace:

或者在管理名称空间中:

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.

当然,对于每个命名空间,这些偏置必须存在,否则会发生错误。现在,每个名称空间的导航将出现在每个控制器上,而不必更改任何控制器或视图。

#6


2  

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)

#7


1  

I don't think there is a cleaner way, and I've seen this somewhere else

我不认为有更干净的方法,我在别的地方见过

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.name.split("::").first
  end
end

#8


1  

I recommend gsub instead of split. It's more effective that split given that you don't need any other module name.

我推荐gsub而不是split。考虑到您不需要任何其他模块名,分割更有效。

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.to_s.gsub(/::.*/, '')
  end
end

#9


1  

With many sub-modules:

有很多子模块:

module ApplicationHelper
  def namespace
    controller.class.name.gsub(/(::)?\w+Controller$/, '')
  end
end

Example: Foo::Bar::BazController => Foo::Bar

例子:Foo:酒吧:BazController Foo = >::酒吧