25

另一个基本的 Rails 问题:

我有一个数据库表,它需要包含对特定数据类型的两个不同记录的引用。

假设的例子:我正在制作一个视频游戏数据库。我有一张“公司”的表格。我希望每个“视频游戏”条目只有一个开发人员和一个发行商。

我知道如果我想拥有一家公司,我可以这样做:

script/generate Videogame company:references

但我需要拥有两家公司。我宁愿不使用连接表,因为给定的数据类型只能有两个,而且我需要它们是不同的。

看起来答案应该很明显,但我在互联网上的任何地方都找不到。

4

3 回答 3

49

只是为了整理一下,在您的迁移中,您现在还可以执行以下操作:

create_table :videogames do |t|
  t.belongs_to :developer
  t.belongs_to :publisher
end

由于您调用键 developer_id 和 publisher_id,模型应该是:

belongs_to :developer, :class_name => "Company"
belongs_to :publisher, :class_name => "Company"

这不是一个大问题,但我发现随着与额外参数的关联数量的增加,事情变得不太清楚,所以最好尽可能坚持默认值。

于 2009-01-06T18:37:32.493 回答
9

我不知道如何使用脚本/生成来做到这一点。

无论如何,不​​使用脚本/生成更容易显示基本思想。您需要视频游戏表/模型中的两个字段来保存公司表/模型的外键。

我将向您展示我认为代码的样子,但我还没有测试过它,所以我可能是错的。

您的迁移文件具有:

create_table :videogames do |t|
  # all your other fields
  t.int :developer_id
  t.int :publisher_id
end

然后在你的模型中:

belongs_to :developer, class_name: "Company", foreign_key: "developer_id"
belongs_to :publisher, class_name: "Company", foreign_key: "publisher_id"

您还提到希望这两家公司是不同的,您可以在检查该developer_id != publisher_id.

于 2009-01-06T17:53:12.520 回答
2

如果您想要特定于某个公司类型的任何方法或验证,您可以对公司模型进行子类化。这采用了一种称为单表继承的技术。有关更多信息,请查看这篇文章:http ://wiki.rubyonrails.org/rails/pages/singletableinheritance

然后,您将拥有:

#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

因此,您可以使用 Company、Developer 和 Publisher 模型。

 Company.find(:all)
 Developer.find(:all)
 Publisher.find(:all)
于 2009-01-07T06:42:01.110 回答