Comment trouver le nom de l'espace de noms ou du module 'Foo' dans le filtre ci-dessous?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
Aucune de ces solutions ne considère une constante avec plusieurs modules parents. Par exemple:
A::B::C
À partir de Rails 3.2.x, vous pouvez simplement:
"A::B::C".deconstantize #=> "A::B"
Depuis Rails 3.1.x vous pouvez:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
En effet, #demodulize est l'opposé de #deconstantize:
"A::B::C".demodulize #=> "C"
Si vous devez vraiment le faire manuellement, essayez ceci:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
Cela devrait le faire:
def get_module_name
@module_name = self.class.to_s.split("::").first
end
Pour le cas simple, vous pouvez utiliser:
self.class.parent
Cela fonctionnerait si le contrôleur avait un nom de module, mais retournerait le nom du contrôleur si ce n'était pas le cas.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
Cependant, si nous changeons cela un peu pour:
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
Vous pouvez déterminer si la classe a un nom de module ou non et renvoyer autre chose que le nom de classe que vous pouvez tester.
my_class.name.underscore.split('/').slice(0..-2)
ou
my_class.name.split('::').slice(0..-2)
Je sais que c'est un vieux fil, mais je viens de découvrir la nécessité d'avoir une navigation distincte en fonction de l'espace de noms du contrôleur. La solution que j'ai trouvée était la suivante dans la disposition de mon application:
<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>
Ce qui semble un peu compliqué mais fait essentiellement ce qui suit - il prend le nom de la classe de contrôleur, qui serait par exemple "People" pour un contrôleur sans espace de nom, et "Admin :: Users" pour un contrôleur à espace de nom. Utilisation de la méthode de chaîne [] avec une expression régulière qui renvoie n'importe quoi avant deux deux points, ou nil s'il n'y a rien. Il change ensuite cela en minuscules (le "try" est là au cas où il n'y a pas d'espace de noms et nil est retourné). Cela nous laisse alors soit avec le namespace soit avec nil. Ensuite, il rend simplement le partiel avec ou sans l'espace de noms, par exemple aucun espace de noms:
app/views/_nav.html.erb
ou dans l'espace de noms admin:
app/views/admin/_nav.html.erb
Bien sûr, ces partiels doivent exister pour chaque espace de noms, sinon une erreur se produit. Maintenant, la navigation pour chaque espace de noms apparaîtra pour chaque contrôleur sans avoir à changer de contrôleur ou de vue.
Je ne pense pas qu'il existe un moyen plus propre, et je l'ai vu ailleurs
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
Je recommande gsub
au lieu de split
. Il est plus efficace que split
étant donné que vous n'avez besoin d'aucun autre nom de module.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
Avec de nombreux sous-modules:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
Exemple: Foo::Bar::BazController
=> Foo::Bar