Como você encontrar o nome do namespace / módulo de programação em Ruby on Rails?

StackOverflow https://stackoverflow.com/questions/133357

  •  02-07-2019
  •  | 
  •  

Pergunta

Como faço para encontrar o nome do namespace ou módulo 'Foo' no filtro abaixo?

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


class Foo::BarController < ApplicationController
  before_filter :get_module_name
end
Foi útil?

Solução

Nenhuma destas soluções considerar uma constante com vários módulos principais. Por exemplo:

A::B::C

A partir de Rails 3.2.x você pode simplesmente:

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

A partir de Rails 3.1.x, você pode:

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

Isto porque #demodulize é o oposto do #deconstantize:

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

Se você realmente precisa fazer isso manualmente, tente o seguinte:

constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]

Outras dicas

Isso deve fazê-lo:

  def get_module_name
    @module_name = self.class.to_s.split("::").first
  end

Para o caso simples, você pode usar:

self.class.parent

Isso poderia funcionar se o controlador tinha um nome do módulo, mas gostaria de voltar o nome do controlador se ele não o fez.

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.name.split("::").first
  end
end

No entanto, se alterar esta um pouco para:

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

Você pode determinar se a classe tem um nome de módulo ou não e retorno outra coisa que não seja o nome da classe que você pode testar para.

Eu sei que esta é uma discussão antiga, mas eu só vim através a necessidade de ter de navegação separado, dependendo do namespace do controlador. A solução que eu vim com foi isso no meu layout do aplicativo:

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

O que parece um pouco complicado, mas basicamente faz o seguinte - que leva o nome da classe do controlador, que seria, por exemplo, "Pessoas" para um controlador não-namespaced e "admin :: Users" para um namespace. Utilizando o método de string [] com uma expressão regular que retorna nada antes de dois dois pontos, ou nulo se não há nada. Em seguida, ele muda nesse caso, para diminuir (a "tentativa" é lá em caso de não haver espaço para nome e nil é retornado). Isso, então, deixa-nos tanto com o namespace ou nula. Em seguida, ele simplesmente torna a parcial com ou sem o namespace, por exemplo, não namespace:

app/views/_nav.html.erb

ou no namespace admin:

app/views/admin/_nav.html.erb

É claro que essas parciais têm de existir para cada namespace caso contrário ocorre um erro. Agora, a navegação para cada namespace aparecerá para cada controlador sem ter que mudar qualquer controlador ou exibição.

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

ou

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

Eu não acho que há um mais limpa maneira, e eu já vi isso em outro lugar

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.name.split("::").first
  end
end

Eu recomendo gsub vez de split. É mais eficaz que split dado que você não precisa de nenhum outro nome do módulo.

class ApplicationController < ActionController::Base
  def get_module_name
    @module_name = self.class.to_s.gsub(/::.*/, '')
  end
end

Com muitos sub-módulos:

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

Exemplo: Foo::Bar::BazController => Foo::Bar

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top