ruby-on-rails - 是否可以创建一个在其行创建时定义的不明确外键?

标签 ruby-on-rails database postgresql ruby-on-rails-3.2

我有两个数据库表,housesapartments。其中每一个都有自己的 View 页面,我希望用户可以对其发表评论。当然,我还有一个 posts 表。创建帖子时,它应该有一个引用适当表(housesapartments)的外键 ID。是否有一种有效的方法可以为 posts 表创建某种类型的模糊外键并在创建时定义它?截至目前,我想到的解决我的问题的最佳方法是创建两个外键 ID(一个用于 houses,一个用于 apartments)并且只有一个每个 post 的列开销。感谢您的帮助!

最佳答案

单表继承 允许将对象定义为单独的类,同时仅使用单个数据库表。这适用于除了轻微行为差异外在结构和功能上相似的对象。

在你的例子中,你有两个子类,HouseApartment,它们非常相似,可以抽象为一个父类(super class),Dwelling。这个父类(super class)将包含房屋和公寓均可访问的常用方法。每个子类都将继承 Dwelling 并使用自己的子类特定方法对其进行扩展。您将像往常一样实例化一个子类,但在内部 Rails 将使用父类(super class)的类型转换实例。因此,您永远不应直接实例化父类(super class)。

值得注意的是,STI 将所有属性合并到一张表中。一个子类的属性将出现在另一个子类中,如果未使用则为nil。具有大量无关属性的子类将导致膨胀的表格充满nil 值。作为一般规则,当您的子类包含的差异多于相似之处时,应考虑多态关联。


这是我们的做法。 所有这些都在 app/models/dwelling.rb 中:

class Dwelling < ActiveRecord::Base
  has_many :posts
  # ...common methods...
end 

class House < Dwelling
  has_many :posts, :foreign_key => "dwelling_id"
  # ...house methods...
end

class Apartment < Dwelling
  has_many :posts, :foreign_key => "dwelling_id"
  # ...apartment methods...
end

为了使其工作,您的dwelling必须包含一个名为“type”的字符串列。 Rails 会看到这一点并自动知道正在使用 STI。注意:应用程序将不再使用 houseapartment 表。创建一个 House 对象会在数据库中保存一个新的住宅记录,它有自己唯一的 ID,它的 type 将是“house”。

将新的 Post 分配给子类时,使用子类对象的 ID。子类 ID 和父类(super class) ID 都引用相同的记录。请注意每个子类中的 has_many 方法。通过调用 @house.posts 获取子类的帖子。

要推断帖子是发布到房屋还是公寓,您可以使用 @post.dwelling.type


编辑:

Rails 3 的自动加载行为要求每个类都在它自己的文件中。因此,子类必须分别在自己的文件中:

app/
  models/
    apartment.rb
    dwelling.rb
    house.rb

关于ruby-on-rails - 是否可以创建一个在其行创建时定义的不明确外键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15914900/

相关文章:

Android Sqlite 如果不存在则插入

postgresql - Typeorm 不想更新数据库

database - Blackberry 的 SQlite 数据库有其他选择吗?

php js mysql下拉选择用db值填充文本框

sql - 在 Oracle、PostgreSQL 和 SQL Server 中比较时间戳的常用方法

sql - 对一张 table 进行Seq Scan的原因是什么?

ruby-on-rails - 跟踪每个循环以查找条件

ruby-on-rails - AppEngine Flex 部署错误 - INVALID_ARGUMENT : The following quotas were exceeded

javascript - 页面刷新后需要勾选复选框

ruby-on-rails - 在 rails3 的连接查询中获取不同的记录