2012-01-18 7 views
17

que tienen la siguiente estructura dirrieles table_name_prefix faltan

models/foo/setting.rb 
models/foo.rb 

contenido foo.rb

module Foo 
    def self.table_name_prefix 
    'foo_' 
    end 
end 

y setting.rb contenido

class Foo::Setting < ActiveRecord::Base 
end 

Tan pronto como me llamo Foo::Setting.find… Recibo un error SQLException: no such table: settings que es correcto porque la tabla se llama foo_settings por lo que los raíles parecen ignorar el prefijo de tabla especificado para el módulo Foo.

¿Qué puedo hacer para que los rieles consideren el prefijo?

+1

¿Qué versión de Rails está usando? – qerub

+0

Como mencionó Qerub, debe verificar su versión de Rails, porque si no me equivoco, esta característica vino de 3.0 – zsquare

+0

Estoy usando Rails 3.2 – gorootde

Respuesta

16

Has definido un método dentro de un módulo (Foo). Esto no define mágicamente ese método en una clase anidada en ese módulo.

me gustaría probar algo así como

class Foo < ActiveRecord::Base 
    self.abstract_class = true 
    self.table_name_prefix = 'foo_' 
end 

Y luego heredar de Foo

class Foo::Setting < Foo 
... 
end 
+1

Los rieles generaron ese módulo y la estructura. ¿Estás seguro? Si es así, 'rails generate' generará algo que no se puede ejecutar. – gorootde

+0

Genera algo ejecutable, simplemente no es algo que hace lo que quieres. Si solo está creando espacios para el nombre de sus modelos, entonces todo lo que necesita es un modo –

+0

El comercio de Spree parece estar utilizando este método también .. https://github.com/spree/spree/blob/master/core/app/models/spree .rb Pero no puedo entender cómo lo han hecho – BigFive

1

que tenía el mismo problema. Lo resolvió cambiando el espacio de nombres de mi aplicación o el modelo.

Echa un vistazo a este question. Usar el mismo espacio de nombres para la aplicación como para los modelos hace que los modelos no recojan el espacio de nombres padre nombre_tabla_prefijo correctamente.

7

Esto es probablemente causado por el autocargador de carriles. Al hacer esto:

module Foo 
    class Bar 
    end 
end 

y luego tratar de utilizar Foo::Bar, el cargador automático intenta localizar app/models/foo/bar.rb primero. El archivo está cargado y aquí se define module Foo (aunque como un módulo que contiene únicamente Bar) por lo que el autocargador nunca intenta cargar app/models/foo.rb.

Esto solo debería ocurrir en el modo de desarrollo, ya que en el modo de producción todos sus archivos son require 'd al inicio.

Hay dos soluciones: Que yo sepa

engañar al cargador automático

declarar su clase utilizando class Foo::Bar, para forzar el cargador automático para resolver una búsqueda constante para Foo.

Esto tiene el efecto secundario molesto que la búsqueda constante en el interior Bar NO será de ámbito dentro Foo, por ejemplo:

# app/models/foo.rb 
module Foo 
BAZ = "baz" 
end 

# app/models/foo/bar.rb 
class Foo::Bar 
    def baz 
    BAZ 
    end 
end 

aquí, Foo::Bar.new.baz se producirá un error, a menos que se hace referencia a la constante usando Foo::BAZ. Esto puede ser realmente un desastre al definir asociaciones ActiveRecord, por ejemplo.

Exigir el módulo

usando require_dependency:

require_dependency 'foo' 
module Foo 
    class Bar 
    end 
end 

Esta es mi humilde opinión la solución adecuada, ya que no se rompa la búsqueda constante, pero también es un poco molesto, ya que tiene que agregue la instrucción require en la parte superior de cada archivo de espacio de nombres.

Nota:

Este error parece haber sido resuelto en los carriles 4. He utilizado la segunda solución mucho mientras que en los carriles 3, pero he tratado de reproducir el error en los carriles 4 y lo hace no aparecer más Creo que modificaron la forma en que funciona el autocargador ... Para obtener más información, consulte the rails guides on autoloading and reloading constants

+0

En algunos casos tengo este error también – GorillaApe

+0

, todavía tenía este error intermitentemente aparece en una ejecución de CI en el trabajo con raíles 4. por lo que no tuvimos que require_dependency requerimos el módulo en un inicializador. prefiero de esta manera en lugar de necesitar require_dependancy porque eso significa que cualquier otro desarrollador que llegue necesitará recordar que también requiere dependencia. – karina

0

Simplemente cree una clase base dentro de su directorio de modelo de espacio de nombres y exija Foo, luego amplíe los modelos desde la clase base.

Decir que tengo app/models/foo.rb

module Foo 
    def self.table_name_prefix 
    'tble_prefix_' 
    end 
end 

Luego, en app/models/foo/base_record.rb

require_dependency 'foo' 
module Foo 
    class BaseRecord < ActiveRecord::Base 
    self.abstract_class = true 
    end 
end 

Luego se extienden desde el BaseRecord

module Foo 
    class Bar < BaseRecord 

    end 
end 
Cuestiones relacionadas