Andaimes ActiveRecord: duas colunas do mesmo tipo de dados
-
03-07-2019 - |
Pergunta
Outra questão básica Rails:
Eu tenho uma tabela de banco de dados que precisa conter referências a exatamente dois registros diferentes de um tipo de dados específico.
hipotético exemplo: Eu estou fazendo um banco de dados de vídeo game. Eu tenho uma tabela de "Empresas". Quero ter exatamente um desenvolvedor e exatamente um editor para cada entrada "Videogame".
Eu sei que se eu quero ter uma empresa, eu só posso fazer algo como:
script/generate Videogame company:references
Mas eu preciso ter ambas as empresas. Eu prefiro não usar uma tabela de junção, como só pode haver exatamente dois do determinado tipo de dados, e eu preciso que eles sejam distintos.
Parece que a resposta deve ser bastante óbvio, mas não posso encontrá-lo em qualquer lugar na Internet.
Solução
Apenas para arrumar as coisas um pouco, em sua migração agora você pode também fazer:
create_table :videogames do |t|
t.belongs_to :developer
t.belongs_to :publisher
end
E uma vez que você está chamando as chaves developer_id e publisher_id, o modelo provavelmente deve ser:
belongs_to :developer, :class_name => "Company"
belongs_to :publisher, :class_name => "Company"
Não é um grande problema, mas eu acho que, como o número de associações com argumentos extras são adicionados, as coisas menos claras tornam-se, por isso é melhor ficar com os padrões sempre que possível.
Outras dicas
Eu não tenho nenhuma idéia de como fazer isso com script / gerar.
A ideia subjacente é mais fácil mostrar sem o uso de script / gerar qualquer maneira. Você quer dois campos na sua tabela de videogames / modelo que detêm as chaves estrangeiras para a empresas de tabela / modelo.
Eu vou te mostrar o que eu pense o código ficaria assim, mas eu não testei isso, para que eu pudesse estar errado.
Seu arquivo de migração tem:
create_table :videogames do |t|
# all your other fields
t.int :developer_id
t.int :publisher_id
end
Então, em seu modelo:
belongs_to :developer, class_name: "Company", foreign_key: "developer_id"
belongs_to :publisher, class_name: "Company", foreign_key: "publisher_id"
Você também mencionam que querem as duas empresas sejam distintos, o que você poderia segurar em uma validação no modelo que os controlos que developer_id != publisher_id
.
Se houver quaisquer métodos ou validação que você quer específica para um determinado tipo de empresa, você poderia subclasse o modelo de empresa. Este emprega uma técnica chamada herança única tabela. Para mais informações confira este artigo: http://wiki.rubyonrails.org/rails/pages/ singletableinheritance
Você teria, então:
#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
Como resultado, você teria Companhia, desenvolvedor e editor modelos para uso.
Company.find(:all)
Developer.find(:all)
Publisher.find(:all)