¿Cómo encuentra el nombre del espacio de nombres / módulo mediante programación en Ruby on Rails?

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

  •  02-07-2019
  •  | 
  •  

Pregunta

¿Cómo puedo encontrar el nombre del espacio de nombres o el módulo 'Foo' en el filtro a continuación?

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


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

Solución

Ninguna de estas soluciones considera una constante con múltiples módulos principales. Por ejemplo:

A::B::C

A partir de Rails 3.2.x puede simplemente:

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

A partir de Rails 3.1.x puede:

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

Esto se debe a que #demodulize es lo opuesto a #deconstantize:

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

Si realmente necesitas hacer esto manualmente, prueba esto:

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

Otros consejos

Esto debería hacerlo:

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

Para el caso simple, puede usar:

self.class.parent

Esto funcionaría si el controlador tuviera un nombre de módulo, pero devolvería el nombre del controlador si no lo tuviera.

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

Sin embargo, si cambiamos esto un poco 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

Puede determinar si la clase tiene un nombre de módulo o no y devolver algo más que el nombre de la clase que puede probar.

Sé que este es un subproceso antiguo, pero acabo de encontrar la necesidad de tener una navegación separada dependiendo del espacio de nombres del controlador. La solución que se me ocurrió fue esta en el diseño de mi aplicación:

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

Lo que parece un poco complicado pero básicamente hace lo siguiente: toma el nombre de la clase del controlador, que sería, por ejemplo, " Gente " para un controlador sin espacio de nombres, y "Admin :: Usuarios" para un espacio de nombre. Usando el método de cadena [] con una expresión regular que devuelve cualquier cosa antes de dos puntos, o nil si no hay nada. Luego lo cambia a minúsculas (el " intentar " está ahí en caso de que no haya espacio de nombres y se devuelva nil). Esto nos deja con el espacio de nombres o nulo. Luego simplemente procesa el parcial con o sin el espacio de nombres, por ejemplo, sin espacio de nombres:

app/views/_nav.html.erb

o en el espacio de nombres de administrador:

app/views/admin/_nav.html.erb

Por supuesto, estos parciales tienen que existir para cada espacio de nombres; de lo contrario, se produce un error. Ahora la navegación para cada espacio de nombre aparecerá para cada controlador sin tener que cambiar ningún controlador o vista.

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

o

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

No creo que haya una manera más limpia , y he visto esto en otro lugar

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

Recomiendo gsub en lugar de split . Es más efectivo que split dado que no necesita ningún otro nombre de módulo.

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

Con muchos submódulos:

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

Ejemplo: Foo :: Bar :: BazController = > Foo::Bar

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top