Come trovare lo spazio dei nomi / il nome del modulo a livello di codice in Ruby on Rails?

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

  •  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
È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top