Rails 3:如何获取当前命名空间?

35

使用方法:layout_for_namespace,我可以根据当前所处的前端或后端(后端是使用名称空间“admin”)设置应用程序的布局。

我找不到一种简单的方法来确定我所在的名称空间,唯一能找到的方法是通过解析params[:controller]中的字符串。当然,这很简单,似乎很安全并且工作良好。但我只是想知道是否有更好、更可靠的方法来完成这个任务。有人知道吗?

目前我只是使用以下方法:

def is_backend_namespace?
  params[:controller].index("admin/") == 0
end

提前感谢

Arne

9个回答

45

您可以使用:

self.class.parent == Admin

1
这个答案应该是第一个! - mmike
9
许多人指出,这种方法无法适用于具有多级命名空间的类。但是,如果你只是想检查是否在这样的命名空间中(就像原帖中所提到的那样),那么你可以使用controller.class.parents.include?(Admin),而不必采用字符串解析来获取类似的结果。 - trcarden
@trcarden,使用该解决方案时我遇到了这个错误:NameError Exception: undefined local variable or method 'controller'。我使用的是Rails 5.1版本。self.class.parents可以正常工作并且等效。 - stwr667

27

在控制器之外(例如在视图中),可以使用controller.class.name。您可以像这样将其转换为帮助方法:

module ApplicationHelper
  def admin?
    controller.class.name.split("::").first=="Admin"
  end
end

谢谢。这是一个简单易用的解决方案,特别适用于需要检查“Views”命名空间的情况。 - Damon Aw
2
在视图中,您也可以使用controller.class.parent.name。 - engineerDave
如何从视图中调用这个函数? - Harsha M V
2
看起来像是肮脏的代码... 我认为使用 class.parent 更清晰。 - mmike

20

无论在控制器还是视图中,您都可以解析controller_path,例如:

namespace = controller_path.split('/').first

如果我输入 'foo'.split('/').first,那么这将返回 'foo'。如果要检查非命名空间的控制器名称,则最好的解决方案是将命名空间设置为 nil - Cristian

11

并没有更加优雅的方式,但是它使用了类(class)而不是参数哈希(params hash)。我不知道有没有一种“准备好”的方法可以在不进行某些解析的情况下完成这个任务。

self.class.to_s.split("::").first=="Admin"

嗨。那不是我想说的,抱歉。控制器的名称是其他东西,“admin”是命名空间。它是Admin :: MyController,所以params [: controller]给出“admin / my_controller”或其他内容,这就是我检查它是否为管理员命名空间的地方。使用controller_name,我必须做同样的事情,但我想知道一种方法,不是_parse_它,而只返回命名空间。 - arnekolja
我的错,我没有仔细阅读问题。您明确指出了命名空间而不是控制器名称。答案已更新为另一种选择。 - johnmcaliley
2
更简单的写法是 controller.class.name.start_with?('Admin') - Patrick Berkeley

10

在应用程序控制器中设置命名空间:

path = self.controller_path.split('/')
@namespace = path.second ? path.first : nil

2
这将避免使用三目运算符:@namespace =(如果path.second,则为path.first) - parndt

10

这些解决方案都没有考虑到有多个父模块的常量。例如:

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]

7

在 Rails 6 中,控制器类似乎没有 namespace 方法。

在视图中,最干净且有效的解决方案是:使用 controller.class.module_parent

具体而言,如果您的命名空间是 Admin:: 并且您想要 'admin',则应该执行: controller.class.module_parent.to_s.downcase


1
似乎在Rails 6.0.3.2中还没有module_parent可用。因此,我使用controller.class.parent - wrystr

2

Rails 6

如何在视图中访问命名空间?

不要使用:controller.namespace.parent == Admin

parent方法将在Rails 6.1中被移除。

DEPRECATION WARNING: `Module#parent` has been renamed to `module_parent`. `parent` is deprecated and will be removed in Rails 6.1.

请使用module_parent代替:

controller.namespace.module_parent == Admin


尝试使用 controller.namespace,但是它报错说 undefined method 'namespace'。我使用的是 Rails 6.0,而 controller.class.parent 则可以正常工作。 - wrystr
对我来说,controller.class.module_parent 起作用了。 - Randomtheories

0
在Rails 6中,您可以这样做:
controller.class.module_parent

获取父模块。尚未尝试多层嵌套。但对于单个,您可以像这样转换为符号:

controller.class.module_parent.to_s.underscore.to_sym

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接