2012-01-18 12 views
17

ho ottenuto la seguente struttura dirRails table_name_prefix mancanti

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

contenuti foo.rb

module Foo 
    def self.table_name_prefix 
    'foo_' 
    end 
end 

e setting.rb contenuti

class Foo::Setting < ActiveRecord::Base 
end 

Appena io chiamo Foo::Setting.find… Ricevo un errore SQLException: no such table: settings che è effettivamente corretto perché la tabella è denominata foo_settings quindi rotaie sembra ignorare il prefisso tabella specificato per il modulo Foo.

Cosa posso fare in modo che il binario consideri il prefisso?

+1

Quale versione di Rails stai usando? – qerub

+0

Come menzionato da Qerub, dovresti controllare la versione di Rails, perché se non sbaglio, questa funzione è arrivata da 3.0 – zsquare

+0

I'am using Rails 3.2 – gorootde

risposta

16

È stato definito un metodo all'interno di un modulo (Foo). Questo non definisce magicamente quel metodo su una classe annidata in quel modulo.

mi piacerebbe provare qualcosa di simile

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

E poi ereditare da Foo

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

Le rotaie hanno generato quel modulo e la struttura. Sei sicuro? Se così 'rails generate' genererà qualcosa che non è eseguibile. – gorootde

+0

Genera qualcosa che è eseguibile, ma non qualcosa che fa ciò che vuoi. Se stai solo giocando con i nomi dei tuoi modelli, allora tutto ciò che ti serve è una modalità di commercio di Sprea –

+0

che usi questo metodo anche ... https://github.com/spree/spree/blob/master/core/app/models/spree .rb Ma non riesco a capire come l'hanno fatto – BigFive

1

ho avuto lo stesso problema. Risolto modificando uno dei namespace della mia applicazione o quello del modello.

Dai un'occhiata a questo question. Usando lo stesso spazio dei nomi per l'applicazione come per i modelli, i modelli non raccolgono correttamente lo spazio dei nomi parent table_name_prefix.

7

Questo è probabilmente causato dal caricatore automatico delle guide. Nel fare questo:

module Foo 
    class Bar 
    end 
end 

e poi cercando di utilizzare Foo::Bar, il caricatore automatico prima tenta di individuare app/models/foo/bar.rb. Il file viene caricato e qui viene definito module Foo (anche se come modulo contenente esclusivamente Bar) in modo che il caricatore automatico non tenti mai di caricare app/models/foo.rb.

Questo dovrebbe accadere solo in modalità sviluppo, come in modalità di produzione tutti i file sono require all'avvio.

ci sono due soluzioni: AFAIK

ingannare il caricatore automatico

dichiarare la classe utilizzando class Foo::Bar, per costringere il caricatore automatico per risolvere una ricerca costante per Foo.

Questo ha l'effetto collaterale fastidioso che la ricerca costante all'interno Bar NON verrà ambito all'interno Foo, per esempio:

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

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

qui, Foo::Bar.new.baz falliranno, a meno che non si fa riferimento alla costante utilizzando Foo::BAZ. Questo può davvero creare confusione quando si definiscono le associazioni ActiveRecord, ad esempio.

necessario il modulo

utilizzando require_dependency:

require_dependency 'foo' 
module Foo 
    class Bar 
    end 
end 

Questa è secondo me la soluzione giusta, in quanto non si rompe la ricerca costante, ma è anche un po 'fastidioso come si deve aggiungi la dichiarazione require in cima a ogni file dello spazio dei nomi.

Nota:

Questo bug sembra essere stato risolto in rotaie 4. Ho usato la seconda soluzione molto mentre su rotaie 3, ma ho cercato di riprodurre il bug in rotaie 4 e lo fa non si presenta più. Penso che abbiano modificato il modo in cui funziona il caricatore automatico. Per ulteriori informazioni, vedere the rails guides on autoloading and reloading constants

+0

In alcuni casi ho anche questo bug – GorillaApe

+0

ho ancora questo bug visualizzato a intermittenza su un CI eseguito al lavoro con rail 4. quindi non abbiamo dovuto require_dependency abbiamo richiesto il modulo in un inizializzatore. preferisco in questo modo piuttosto che aver bisogno di require_dependancy perché ciò significa che qualsiasi altro dev che si presenta dovrà ricordare di richiedere anche la dipendenza. – karina

0

Basta creare una classe base all'interno della directory del modello con spazio dei nomi e richiedere Foo in esso, quindi estendere i modelli dalla classe base.

Dire che ho app/models/foo.rb

module Foo 
    def self.table_name_prefix 
    'tble_prefix_' 
    end 
end 

Poi nel app/models/foo/base_record.rb

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

quindi estendere dal BaseRecord

module Foo 
    class Bar < BaseRecord 

    end 
end