我有两个数据库表,houses
和 apartments
。其中每一个都有自己的 View 页面,我希望用户可以对其发表评论。当然,我还有一个 posts
表。创建帖子时,它应该有一个引用适当表(houses
或 apartments
)的外键 ID。是否有一种有效的方法可以为 posts
表创建某种类型的模糊外键并在创建时定义它?截至目前,我想到的解决我的问题的最佳方法是创建两个外键 ID(一个用于 houses
,一个用于 apartments
)并且只有一个每个 post
的列开销。感谢您的帮助!
最佳答案
单表继承 允许将对象定义为单独的类,同时仅使用单个数据库表。这适用于除了轻微行为差异外在结构和功能上相似的对象。
在你的例子中,你有两个子类,House
和 Apartment
,它们非常相似,可以抽象为一个父类(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。注意:应用程序将不再使用 house
和 apartment
表。创建一个 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/