How do you find the namespace/module name programmatically in Ruby on Rails?
Ruby on-RailsRubyNamespacesRuby on-Rails Problem Overview
How do I find the name of the namespace or module 'Foo' in the filter below?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
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]
Solution 2 - Ruby on-Rails
For the simple case, You can use :
self.class.parent
Solution 3 - Ruby on-Rails
This should do it:
def get_module_name
@module_name = self.class.to_s.split("::").first
end
Solution 4 - Ruby on-Rails
For Rails 6.1
self.class.module_parent
Hettomei answer works fine up to Rails 6.0
> DEPRECATION WARNING: Module#parent
has been renamed to module_parent
. parent
is deprecated and will be removed in Rails 6.1.
Solution 5 - Ruby on-Rails
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.
Solution 6 - Ruby on-Rails
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:
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.
Solution 7 - Ruby on-Rails
my_class.name.underscore.split('/').slice(0..-2)
or
my_class.name.split('::').slice(0..-2)
Solution 8 - Ruby on-Rails
No one has mentioned using 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
Solution 9 - Ruby on-Rails
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
Solution 10 - Ruby on-Rails
I recommend gsub
instead of split
. It's more effective that split
given that you don't need any other module name.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
Solution 11 - Ruby on-Rails
With many sub-modules:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
Example: Foo::Bar::BazController
=> Foo::Bar