Ponteggi ActiveRecord: due colonne dello stesso tipo di dati
-
03-07-2019 - |
Domanda
Un'altra domanda di base su Rails:
Ho una tabella di database che deve contenere riferimenti esattamente a due record diversi di un tipo di dati specifico.
Esempio ipotetico: sto creando un database di videogiochi. Ho una tabella per " Aziende. & Quot; Voglio avere esattamente uno sviluppatore e esattamente un editore per ogni "Videogioco" ingresso.
So che se voglio avere una società, posso semplicemente fare qualcosa del tipo:
script/generate Videogame company:references
Ma devo avere entrambe le società. Preferirei non utilizzare una tabella di join, poiché possono esserci solo due esattamente del tipo di dati specificato e ho bisogno che siano distinti.
Sembra che la risposta dovrebbe essere abbastanza ovvia, ma non riesco a trovarla da nessuna parte su Internet.
Soluzione
Solo per sistemare un po 'le cose, nella tua migrazione ora puoi anche fare:
create_table :videogames do |t|
t.belongs_to :developer
t.belongs_to :publisher
end
E poiché stai chiamando le chiavi developer_id e publisher_id, il modello dovrebbe probabilmente essere:
belongs_to :developer, :class_name => "Company"
belongs_to :publisher, :class_name => "Company"
Non è un grosso problema, ma trovo che man mano che il numero di associazioni con argomenti extra viene aggiunto, diventano meno chiare le cose, quindi è meglio attenersi alle impostazioni predefinite ogni volta che è possibile.
Altri suggerimenti
Non ho idea di come farlo con script / generate.
L'idea alla base è più facile da mostrare senza usare lo script / generare comunque. Desideri due campi nella tabella / modello dei tuoi videogiochi che contengano le chiavi esterne della tabella / modello delle aziende.
Ti mostrerò come penso come sarebbe il codice, ma non l'ho provato, quindi potrei sbagliarmi.
Il tuo file di migrazione ha:
create_table :videogames do |t|
# all your other fields
t.int :developer_id
t.int :publisher_id
end
Quindi nel tuo modello:
belongs_to :developer, class_name: "Company", foreign_key: "developer_id"
belongs_to :publisher, class_name: "Company", foreign_key: "publisher_id"
Si menziona anche il desiderio di distinguere le due società, che è possibile gestire in una convalida nel modello che verifica che developer_id! = publisher_id
.
Se sono presenti metodi o convalide specifici per un determinato tipo di azienda, è possibile sottoclassare il modello dell'azienda. Questo utilizza una tecnica chiamata ereditarietà a tabella singola. Per ulteriori informazioni, consulta questo articolo: http://wiki.rubyonrails.org/rails/pages/ singletableinheritance
Avresti quindi:
#db/migrate/###_create_companies
class CreateCompanies < ActiveRecord::Migration
def self.up
create_table :companies do |t|
t.string :type # required so rails know what type of company a record is
t.timestamps
end
end
def self.down
drop_table :companies
end
end
#db/migrate/###_create_videogames
class CreateVideogames < ActiveRecord::Migration
create_table :videogames do |t|
t.belongs_to :developer
t.belongs_to :publisher
end
def self.down
drop_table :videogames
end
end
#app/models/company.rb
class Company < ActiveRecord::Base
has_many :videogames
common validations and methods
end
#app/models/developer.rb
class Developer < Company
developer specific code
end
#app/models/publisher.rb
class Publisher < Company
publisher specific code
end
#app/models/videogame.rb
class Videogame < ActiveRecord::Base
belongs_to :developer, :publisher
end
Di conseguenza, avresti a disposizione modelli di società, sviluppatori ed editori.
Company.find(:all)
Developer.find(:all)
Publisher.find(:all)