Scaffolding ActiveRecord:两列相同的数据类型

时间:2009-01-06 16:59:52

标签: ruby-on-rails ruby activerecord scaffolding

另一个基本的Rails问题:

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

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

我知道如果我想拥有一家公司,我可以做类似的事情:

script/generate Videogame company:references

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

似乎答案应该非常明显,但我无法在互联网上找到它。

3 个答案:

答案 0 :(得分:46)

只是为了整理一下,在您的迁移中,您现在也可以这样做:

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"

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

答案 1 :(得分:9)

我不知道如何使用script / generate执行此操作。

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

我会告诉你我认为代码会是什么样子,但我没有测试过,所以我可能错了。

您的迁移文件包含:

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的模型中进行验证。

答案 2 :(得分: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)