Rails 3: Get current namespace?
Asked Answered
S

9

35

using a method :layout_for_namespace I set my app's layout depending on whether I am in frontend or backend, as the backend is using an namespace "admin".

I could not find a pretty way to find out which namespace I am, the only way I found is by parsing the string from params[:controller]. Of course that's easy, seems to be fail-safe and working good. But I am just wondering if there's a better, prepared, way to do this. Does anyone know?

Currently I am just using the following method:

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

Thanks in advance

Arne

Skimmia answered 19/11, 2010 at 15:41 Comment(0)
B
45

You can use:

self.class.parent == Admin
Baldheaded answered 22/2, 2013 at 16:25 Comment(3)
this answer should be first one!Shorts
As many have pointed out this doesn't work for classes that have multiple levels of namespacing. However if you are just checking to see if you are in such a namespace (like the OP kind of was getting at) then you can use controller.class.parents.include?(Admin) and get at the similar thing without having to resort to string parsingIslamite
@Islamite I get this error with that solution: NameError Exception: undefined local variable or method 'controller'. I'm on Rails 5.1. self.class.parents works and is equivalent.Chromatophore
B
27

Outside the controller (e.g. in the views), use controller.class.name. You can turn this into a helper method like this:

module ApplicationHelper
  def admin?
    controller.class.name.split("::").first=="Admin"
  end
end
Brasher answered 19/4, 2011 at 15:16 Comment(4)
Thanks. It's a simple and easy to use solution, especially when you need to check the namespace in Views.Zippora
also in the views you can use controller.class.parent.nameRokach
how to call this from the view?Dwayne
looks like dirty code... I think more clear to use class.parentShorts
F
20

In both the controller and the views, you can parse controller_path, eg.:

namespace = controller_path.split('/').first
Fascism answered 25/1, 2012 at 14:48 Comment(1)
this gives 'foo' back if I say 'foo'.split('/').first . A solution would be best if namespace is nil when checking a non-namespaced controller nameSwat
I
11

Not much more elegant, but it uses the class instead of the params hash. I am not aware of a "prepared" way to do this without some parsing.

self.class.to_s.split("::").first=="Admin"
Interjection answered 19/11, 2010 at 18:58 Comment(3)
Hi. That's not what I meant, sorry. The controller's name is something else, "admin" is the namespace. It's Admin::MyController, so params[:controller] gives "admin/my_controller" or something, thats where I check if it is the admin namespace. Using controller_name I would have to do just the same, but I'd like to know a way to not parse it but get back the namespace only.Skimmia
My fault, I didn't read the question closely. You clearly state namespace and not controller name. Answer updated with an alternative.Interjection
More simply controller.class.name.start_with?('Admin').Ussery
H
10

Setting the namespace in application controller:

path = self.controller_path.split('/')
@namespace = path.second ? path.first : nil
Handicraftsman answered 14/4, 2012 at 20:34 Comment(1)
This would obviate the ternary: @namespace = (path.first if path.second)Egoist
H
10

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:

"A::B::C".deconstantize #=> "A::B"

As of Rails 3.1.x you can:

constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )

This is because #demodulize is the opposite of #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]
Hypermeter answered 3/1, 2013 at 19:25 Comment(0)
V
7

In Rails 6, the controller class does not seem to have a namespace method on it.

The solution that seemed cleanest and worked for me in a view was: controller.class.module_parent

Specifically, if your namespace is Admin:: and you wanted 'admin', you'd do: controller.class.module_parent.to_s.downcase

Voracity answered 27/3, 2020 at 14:37 Comment(2)
Seems like module_parent is not available yet in Rails 6.0.3.2. So, I use controller.class.parentPhila
This doesn't work if you have nested controllers ``` Admin::Accounts::SubAccountsController ``` gives you ``` Admin::Accounts ```Junkie
S
2

Rails 6

Accessing the namespace in the view?

do not use: controller.namespace.parent == Admin

the parent method will be removed in Rails 6.1

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

use module_parent instead:

controller.namespace.module_parent == Admin

Saponin answered 26/11, 2019 at 16:22 Comment(2)
Tried controller.namespace, but it says undefined method 'namespace'. I used rails 6.0 and controller.class.parent worksPhila
For me controller.class.module_parent workedAdversary
A
0

In Rails 6 you can do:

controller.class.module_parent

to get the parent module. Haven't tried it with multiple nestings. But for one you can convert to a symbol like this:

controller.class.module_parent.to_s.underscore.to_sym
Adversary answered 19/7, 2022 at 6:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.