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

如何在下面的过滤器中找到名称空间或模块“ Foo”的名称?

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = ???
  end
end


class Foo::BarController < ApplicationController
  before_filter :get_module_name
end
Steropes asked 2019-11-17T16:01:36Z
9个解决方案
98 votes

这些解决方案均未考虑具有多个父模块的常量。 例如:

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]
Jason Harrelson answered 2019-11-17T16:02:41Z
24 votes

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

self.class.parent
Hettomei answered 2019-11-17T16:03:10Z
22 votes

这应该这样做:

  def get_module_name
    @module_name = self.class.to_s.split("::").first
  end
Daniel Lucraft answered 2019-11-17T16:03:29Z
6 votes

如果控制器确实具有模块名称,这将起作用,但如果没有模块名称,则将返回控制器名称。

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

您可以确定该类是否具有模块名称,然后返回可以测试的类名称以外的其他名称。

Steropes answered 2019-11-17T16:04:09Z
2 votes

我知道这是一个旧线程,但是我碰到了需要根据控制器的名称空间进行单独导航的需求。 我想出的解决方案是在我的应用程序布局中:

<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>

看起来有点复杂,但基本上可以执行以下操作-它采用控制器类名称,例如,对于没有命名空间的控制器,它将为“ People”,对于命名空间的控制器将为“ Admin :: Users”。 将[]字符串方法与正则表达式一起使用,该正则表达式返回两个冒号之前的任何内容;如果不存在任何内容,则返回nil。 然后将其更改为小写(如果没有名称空间并返回nil,则存在“ try”)。 然后,这给我们留下了名称空间或nil。 然后,它仅使用或不使用名称空间(例如,不使用名称空间)呈现部分视图:

app/views/_nav.html.erb

或在admin名称空间中:

app/views/admin/_nav.html.erb

当然,每个命名空间都必须存在这些部分,否则会发生错误。 现在,将为每个控制器显示每个名称空间的导航,而无需更改任何控制器或视图。

Dave Hollingworth answered 2019-11-17T16:05:00Z
2 votes

my_class.name.underscore.split('/').slice(0..-2)

要么

my_class.name.split('::').slice(0..-2)

sandstrom answered 2019-11-17T16:05:33Z
1 votes

我认为没有更清洁的方法,而我在其他地方也看到了

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.name.split("::").first
  end
end
answered 2019-11-17T16:05:59Z
1 votes

我建议使用gsub而不是split。鉴于您不需要任何其他模块名称,因此split会更有效。

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.to_s.gsub(/::.*/, '')
  end
end
Pablo Cantero answered 2019-11-17T16:06:27Z
0 votes

有许多子模块:

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

例如:Foo::Bar::BazController => Foo::Bar

Cyril answered 2019-11-17T16:06:58Z
translate from https://stackoverflow.com:/questions/133357/how-do-you-find-the-namespace-module-name-programmatically-in-ruby-on-rails