Comment trouvez-vous le nom de l'espace de nom / du module par programme dans Ruby on Rails?
-
02-07-2019 - |
Question
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
La solution
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"
À partir de Rails 3.1.x, vous pouvez:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
C'est parce que #demodulize est l'opposé de #deconstantize:
"A::B::C".demodulize #=> "C"
Si vous avez vraiment besoin de le faire manuellement, essayez ceci:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
Autres conseils
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 renverrait le nom du contrôleur s'il ne le possédait pas.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
Cependant, si nous modifions cela un peu en:
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 la classe que vous pouvez tester.
Je sais que c’est un vieux fil de discussion, mais j’ai juste eu le besoin d’avoir une navigation séparée en fonction de l’espace de noms du contrôleur. La solution que j'ai trouvée est la suivante:
<%= 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 du contrôleur, qui serait par exemple "Personnes". pour un contrôleur non-namespaced, et " Admin :: Users " pour un nom. Utilisation de la méthode de chaîne [] avec une expression régulière qui retourne tout ce qui précède les deux points, ou nil s'il n'y a rien. Il change ensuite cette valeur en minuscule (l'option "essayer" existe dans le cas où il n'y a pas d'espace de nom et que nil est renvoyé). Cela nous laisse alors avec l'espace de noms ou nil. Ensuite, il rend simplement le partiel avec ou sans l'espace de nom, par exemple, aucun espace de nom:
app/views/_nav.html.erb
ou dans l'espace de noms administrateur:
app/views/admin/_nav.html.erb
Bien entendu, ces partiels doivent exister pour chaque espace de noms, sinon une erreur se produit. Maintenant, la navigation pour chaque espace de noms apparaît pour chaque contrôleur sans avoir à changer de contrôleur ou de vue.
mon_classe.nom.underscore.split ('/'). slice (0 ..- 2)
ou
mon_classe.nom.split ('::'). slice (0 ..- 2)
Je ne pense pas qu'il existe un moyen plus propre , et je l'ai déjà 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