2009-12-11 7 views
19

Sono nuovo di RoR e sto ancora giocando con le associazioni. Ho bisogno di avere due riferimenti a un modello particolare in un altro modello. Il codice scaffolded non funziona e ottengo un errore "costante non inizializzata".Associazione Rails per due chiavi esterne per lo stesso tavolo in una tabella

comandi generata in:

script/generate scaffold BaseModel name:string 
script/generate scaffold NewModel name:string base1:references base2:references 
db:migrate 

modelli generati:

class NewModel < ActiveRecord::Base 
    belongs_to :base1 
    belongs_to :base2 
end 

e

class BaseModel < ActiveRecord::Base 
    has_many :new_models # I added this line 
end 

Quando provo a creare un Nuovo_modello a /new_models/new, ho provato sia l'ID e il nome del BaseModel ma non funziona. L'errore che ottengo è:

uninitialized constant NewModel::Base1 

ho indovinato mappa i nomi, in modo da creare nel mio metodo, ho cercato di impostare in modo esplicito le istanze BaseModel:

@new_model = NewModel.new(params[:new_model]) 
@base1 = BaseModel.find(1) # this exists 
@base2 = BaseModel.find(2) # this exists 
@new_model.base1 = @base1 # This throws the same error as above 

c'è qualcosa che mi manca?

risposta

31

La maggior parte della magia della Rotaia deriva dalla convenzione sulla configurazione. Denominando le cose secondo le linee guida Rails può indovinare la maggior parte delle opzioni di configurazione. ActiveRecord :: Le associazioni non fanno eccezione.

Il primo argomento di qualsiasi associazione ActiveRecord è il nome che verrà utilizzato all'interno del modello. Questo di solito è il nome di un altro modello, questa è la convenzione. Per impostazione predefinita, il nome della classe è il singolare del nome dell'associazione in Camelcase. La chiave esterna predefinita nell'associazione è il nome dell'associazione postfixed con "_id". Se il nome dell'associazione non corrisponde a un nome di classe o a una chiave esterna in base a questi modelli, sarà necessario fornirli come opzioni.

Questo farà quello che vuoi:

class NewModel 
    belongs_to :base1, :class_name => "BaseModel" 
    belongs_to :base2, :class_name => "BaseModel" 
end 

Personalmente mi sento di dare alle associazioni nomi più descrittivi che Base1 e Base2. Qualcosa di simile a questo:

Valutazioni tabella: id, rater_id, rated_id, voto

class Rating 
    belongs_to :rater, :class_name => "User" 
    belongs_to :rated_user, :class_name => "User", :foreign_key => "rated_id" 
end 

Un esempio diverso avrebbe potuto essere utilizzato, ma questo è stato scelto per mettere in evidenza quando l'opzione chiave esterna è necessaria.

0

Il simbolo trasmesso al metodo belongs_to deve essere il nome singolare dell'altro modello. Così, per il tuo esempio, sarebbe:

class NewModel < ActiveRecord::Base 
    belongs_to :base_model 
end