Come trovare lo spazio dei nomi / il nome del modulo a livello di codice in Ruby on Rails?
-
02-07-2019 - |
Domanda
Come posso trovare il nome dello spazio dei nomi o del modulo 'Foo' nel filtro qui sotto?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
Soluzione
Nessuna di queste soluzioni considera una costante con più moduli padre. Ad esempio:
A::B::C
A partire da Rails 3.2.x puoi semplicemente:
"A::B::C".deconstantize #=> "A::B"
A partire da Rails 3.1.x puoi:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
Questo perché #demodulize è l'opposto di #deconstantize:
"A::B::C".demodulize #=> "C"
Se hai davvero bisogno di farlo manualmente, prova questo:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
Altri suggerimenti
Questo dovrebbe farlo:
def get_module_name
@module_name = self.class.to_s.split("::").first
end
Per il semplice caso, puoi usare:
self.class.parent
Funzionerebbe se il controller avesse un nome di modulo, ma restituirebbe il nome del controller se non lo avesse fatto.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
Tuttavia, se lo cambiamo un po 'in:
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
Puoi determinare se la classe ha un nome del modulo o meno e restituire qualcos'altro diverso dal nome della classe per cui puoi testare.
So che questo è un vecchio thread, ma mi sono appena imbattuto nella necessità di avere una navigazione separata a seconda dello spazio dei nomi del controller. La soluzione che mi è venuta in mente è stata questa nel layout della mia applicazione:
<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>
Il che sembra un po 'complicato ma sostanzialmente fa quanto segue: prende il nome della classe del controller, che sarebbe ad esempio "Persone" per un controller senza spazio dei nomi e " Admin :: Users " per uno spaziale. Usando il metodo stringa [] con un'espressione regolare che restituisce qualcosa prima di due punti, o zero se non c'è nulla. Quindi cambia in minuscolo (il simbolo "try" è presente nel caso in cui non vi sia spazio dei nomi e viene restituito zero). Questo ci lascia quindi con lo spazio dei nomi o zero. Quindi esegue semplicemente il rendering del parziale con o senza lo spazio dei nomi, ad esempio nessuno spazio dei nomi:
app/views/_nav.html.erb
o nello spazio dei nomi dell'amministratore:
app/views/admin/_nav.html.erb
Naturalmente questi parziali devono esistere per ogni spazio dei nomi, altrimenti si verifica un errore. Ora la navigazione per ogni spazio dei nomi apparirà per ogni controller senza dover cambiare alcun controller o vista.
my_class.name.underscore.split ( '/'). Slice (0 ..- 2)
o
my_class.name.split ( '::'). Slice (0 ..- 2)
Non credo che esista un modo più pulito , e l'ho visto da qualche altra parte
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
Raccomando gsub
invece di split
. È più efficace che split
dato che non ti serva nessun altro nome di modulo.
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
Con molti sottomoduli:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
Esempio: Foo :: Bar :: BazController
= > Foo :: Bar