How do you find the namespace/module name programmatically in Ruby on Rails?

Ruby on-RailsRubyNamespaces

Ruby 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteropesView Question on Stackoverflow
Solution 1 - Ruby on-RailsJason HarrelsonView Answer on Stackoverflow
Solution 2 - Ruby on-RailsHettomeiView Answer on Stackoverflow
Solution 3 - Ruby on-RailsDaniel LucraftView Answer on Stackoverflow
Solution 4 - Ruby on-RailsHoracioView Answer on Stackoverflow
Solution 5 - Ruby on-RailsSteropesView Answer on Stackoverflow
Solution 6 - Ruby on-RailsDave HollingworthView Answer on Stackoverflow
Solution 7 - Ruby on-RailssandstromView Answer on Stackoverflow
Solution 8 - Ruby on-RailsCRandERView Answer on Stackoverflow
Solution 9 - Ruby on-RailskokeView Answer on Stackoverflow
Solution 10 - Ruby on-RailsPablo CanteroView Answer on Stackoverflow
Solution 11 - Ruby on-RailsCyrilView Answer on Stackoverflow