【问题标题】:Scaffolding ActiveRecord: two columns of the same data type脚手架 ActiveRecord:相同数据类型的两列
【发布时间】:2009-01-06 16:59:52
【问题描述】:

另一个基本的 Rails 问题:

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

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

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

script/generate Videogame company:references

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

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

【问题讨论】:

    标签: ruby-on-rails ruby activerecord scaffolding


    【解决方案1】:

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

    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"
    

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

    【讨论】:

    • 我试过了,现在有 developer_id 但无法访问 game.developer。我在我的视频游戏类 attr_accessible :developer.
    • 这可能已经解决了,但是您是否已将 has_many :games(或类似的东西)添加到您的开发者模型中?
    • 如何进行反向映射?
    【解决方案2】:

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

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

    我将向您展示我认为代码的样子,但我尚未对其进行测试,所以我可能是错的。

    您的迁移文件有:

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

    【讨论】:

    • 附带说明一下,这里的foreign_key参数是不必要的,因为默认是关联名称+“_id”。有关更多信息,请参阅spacevatican.org/2008/5/6/…
    【解决方案3】:

    如果您想要特定于某个公司类型的任何方法或验证,您可以对公司模型进行子类化。这采用了一种称为单表继承的技术。欲了解更多信息,请查看这篇文章: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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      • 2015-02-05
      • 2014-05-22
      • 1970-01-01
      相关资源
      最近更新 更多