ror root_path rails examples ruby-on-rails ruby ruby-on-rails-3 namespaces

ruby on rails - root_path - Modelo espaciado por nombre en Rails que genera NameError: constante no inicializada



routes ror (2)

Tengo una estructura de carpetas como esta:

app/ models/ bar/ foo.rb connection.rb foo.rb

connection.rb es una "clase abstracta" para conectarse a otra base de datos, entonces:

class Bar::Connection < ActiveRecord::Base self.abstract_class = true establish_connection "outsidedb_#{Rails.env}" end

bar/foo.rb es para acceder a la tabla de foos desde outsidedb , entonces:

class Bar::Foo < Bar::Connection end

Y foo.rb es para acceder a la tabla de los foos desde la base de datos de la aplicación, así que:

class Foo < ActiveRecord::Base end

Desde la consola de rieles, si hago Foo.first o Bar::Foo.first las Bar::Foo.first cosas se comportan como esperaría, obtengo la primera entrada de la tabla de los foos de la aplicación db y la db externa, respectivamente.

Sin embargo, si intento acceder a Foo desde bar/foo.rb obtengo lo siguiente:

class Bar::Foo < Bar::Connection def self.test Bar::Foo.first #=> works Foo.first #=> NameError: uninitialized constant Bar::Foo::Foo end def self.other_test Foo.parent #=> Object Foo.superclass #=> ActiveRecord::Base Object::Foo.first #=> works ActiveRecord::Base::Foo.first #=> works, but with "warning: toplevel constant # Foo referenced by ActiveRecord::Base::Foo end end

Obviamente puedo hacer que las cosas funcionen, pero estoy buscando una mejor comprensión de lo que está pasando. Asumo que me falta algo entre la constante / evaluación de clase de Ruby y la carga automática integrada de Rail ...

  1. ¿Qué es el regreso de .parent (no la clase ''padre'')?
  2. ¿Por qué obtengo el error en .test , pero no lo obtengo en la consola de rails?
  3. ¿Por qué Object::Foo parece funcionar? ¿Es lo correcto?
  4. ¿Por qué funciona ActiveRecord::Base::Foo , pero con una advertencia?
  5. Hay una manera más de hacer todo lo que he hecho sin cambiar el nombre de una de mis clases foo.rb ?

¡Estoy en Rails ''3.2.13'' y Ruby 1.9.3-p194 , solo para que lo sepan!


Aquí hay documentación sobre el método .parent que debería ayudar a responder su primera pregunta: http://guides.rubyonrails.org/active_support_core_extensions.html#extensions-to-module-parents . Desplácese hasta la Sección 3.3 para la parte relevante.

El método .parent viene con soporte activo que proporciona extensiones de Ruby a los componentes de Ruby on Rails. El método .parent es una extensión para Módulos y devuelve el nombre del módulo que contiene la clase actual. Entonces, si lo hizo Bar::Foo.parent , el valor de retorno debería ser Bar .

Sin embargo, cuando la clase no tiene un módulo adjunto, el valor de retorno se configurará por defecto en Object . Esto es lo que sucede cuando haces Foo.parent ya que Foo aquí se refiere a la clase Foo que no está en el espacio de nombres de Bar .

La magia relevante de Rails: https://github.com/rails/rails/blob/c9bbac46ddfc68caff6cd8a95c8d0fd045bd9201/activesupport/lib/active_support/core_ext/module/introspection.rb


Tu problema puede ser arreglado con

::Foo.first

Aquí ::Foo indica la clase Foo en el espacio de nombres superior.

Tu problema proviene del hecho de que hay otra clase de Foo en el espacio de nombres ( Bar ) en el que estás trabajando. Por lo tanto, debes ser explícito.

En cuanto a la pregunta por qué Object::Foo funciona (con advertencias), es un comportamiento (menos) conocido de búsqueda de nombre en Ruby. Por favor, mira este artículo para más detalles.