Ruby on rails 为引用自己表的外键创建Rails 5迁移
我正在写一个显示家谱的小狗数据库。 我有一个postgresql表“dogs”,它有一个dog\u id、名称、重量等。 我还希望它有一个母亲id和一个父亲id来存储另一个狗id 首先,这样做有效吗? 我将如何为Rails5编写迁移Ruby on rails 为引用自己表的外键创建Rails 5迁移,ruby-on-rails,postgresql,ruby-on-rails-5,rails-activerecord,rails-migrations,Ruby On Rails,Postgresql,Ruby On Rails 5,Rails Activerecord,Rails Migrations,我正在写一个显示家谱的小狗数据库。 我有一个postgresql表“dogs”,它有一个dog\u id、名称、重量等。 我还希望它有一个母亲id和一个父亲id来存储另一个狗id 首先,这样做有效吗? 我将如何为Rails5编写迁移 或者我应该有另一张表格“parentage”,它只是把狗和其他狗联系在一起?肯定至少要有第二张表格 我建议添加一个配对或窝模型,并将您的狗与之对应,因为繁殖者可能会再次拥有相同的配对 P>由于层次结构在性能上存在问题,而且使用更深层次的嵌套数据,您可以考虑为另一个
或者我应该有另一张表格“parentage”,它只是把狗和其他狗联系在一起?肯定至少要有第二张表格 我建议添加一个配对或窝模型,并将您的狗与之对应,因为繁殖者可能会再次拥有相同的配对 <> P>由于层次结构在性能上存在问题,而且使用更深层次的嵌套数据,您可以考虑为另一个或两个表中的每个狗存储祖先,以便能够对网站快速检索它们。
我建议,因为它在这种情况下提供了最好的性能(经常阅读,不经常编写)。肯定要至少使用第二个表 我建议添加一个配对或窝模型,并将您的狗与之对应,因为繁殖者可能会再次拥有相同的配对 <> P>由于层次结构在性能上存在问题,而且使用更深层次的嵌套数据,您可以考虑为另一个或两个表中的每个狗存储祖先,以便能够对网站快速检索它们。
我建议,因为它在这种情况下提供了最好的性能(经常阅读,不经常写作)。我不同意neongrau的观点。你不需要第二张桌子就能做到这一点。它可以通过在您的dogs表中创建动态自联接来完成。首先在单个模型中声明所有关系,并分别声明它们的外键: models/dog.rb:
class Dog < ActiveRecord::Base
belongs_to :mom, class_name: "Dog", foreign_key: "mom_id"
belongs_to :dad, class_name: "Dog", foreign_key: "dad_id"
has_many :kids, class_name: "Dog"
end
classdog
然后,您将运行一个引用爸爸妈妈的迁移:
class CreateDogs < ActiveRecord::Migration
def change
create_table :dogs do |t|
t.string :name
t.integer :age
t.references :mom
t.references :dad
t.integer :dog_id
t.timestamps null: false
end
end
class CreateDogs
现在我们通过手动建立关联来测试它:
kid = Dog.create(name: "Rover")
=> #<Dog id: 8, name: "Rover"..>
ma = Dog.create(name: "Susie")
=> #<Dog id: 2, name: "Susie"..>
pa = Dog.create(name: "Doug")
=> #<Dog id: 8, name: "Doug"..>
kid.mom_id = 2
kid.save
kid.mom
=> #<Dog id: 2, name: "Susie"...>
kid.dad_id = 3
kid.save
kid.dad
=> #<Dog id: 3, name: "Doug"...>
ma.kids << kid
ma.save
ma.kids
=> #<Dog id: 1, name: "Rover"...>
pa.kids << kid
pa.save
pa.kids
=> #<Dog id: 1, name: "Rover"...>
kid=Dog.create(名称:“漫游者”)
=> #
ma=Dog.create(名称:“Susie”)
=> #
pa=狗。创建(名称:“Doug”)
=> #
kid.mom_id=2
孩子,救命
孩子,妈妈
=> #
kid.dad_id=3
孩子,救命
孩子,爸爸
=> #
妈妈,孩子们#
爸爸,孩子们#
现在你有了一个动态的关系,狗可以有多个孩子,可能属于父母。我不同意neongrau的观点。你不需要第二张桌子就能做到这一点。它可以通过在您的dogs表中创建动态自联接来完成。首先在单个模型中声明所有关系,并分别声明它们的外键: models/dog.rb:
class Dog < ActiveRecord::Base
belongs_to :mom, class_name: "Dog", foreign_key: "mom_id"
belongs_to :dad, class_name: "Dog", foreign_key: "dad_id"
has_many :kids, class_name: "Dog"
end
classdog
然后,您将运行一个引用爸爸妈妈的迁移:
class CreateDogs < ActiveRecord::Migration
def change
create_table :dogs do |t|
t.string :name
t.integer :age
t.references :mom
t.references :dad
t.integer :dog_id
t.timestamps null: false
end
end
class CreateDogs
现在我们通过手动建立关联来测试它:
kid = Dog.create(name: "Rover")
=> #<Dog id: 8, name: "Rover"..>
ma = Dog.create(name: "Susie")
=> #<Dog id: 2, name: "Susie"..>
pa = Dog.create(name: "Doug")
=> #<Dog id: 8, name: "Doug"..>
kid.mom_id = 2
kid.save
kid.mom
=> #<Dog id: 2, name: "Susie"...>
kid.dad_id = 3
kid.save
kid.dad
=> #<Dog id: 3, name: "Doug"...>
ma.kids << kid
ma.save
ma.kids
=> #<Dog id: 1, name: "Rover"...>
pa.kids << kid
pa.save
pa.kids
=> #<Dog id: 1, name: "Rover"...>
kid=Dog.create(名称:“漫游者”)
=> #
ma=Dog.create(名称:“Susie”)
=> #
pa=狗。创建(名称:“Doug”)
=> #
kid.mom_id=2
孩子,救命
孩子,妈妈
=> #
kid.dad_id=3
孩子,救命
孩子,爸爸
=> #
妈妈,孩子们#
爸爸,孩子们#
现在,你有了一个动态的关系,狗可以有多个孩子,可能属于一个母亲和父亲。很高兴不同意你的观点;)STI很好,也很简单,但是当您需要遍历一棵树时,对于祖先中的每个级别(妈妈和爸爸),您都会遇到一个n+2 sql查询问题。因此,对于曾祖父母,您已经在使用n+2+4+8 sql查询来呈现家谱了。站点性能将不存在。所有内容都可以缓存。你可以创建一个方法来加载ID的嵌套,缓存它并让迭代器使用它。我确实明白neongrau关于性能的观点,我将研究用于重构的便捷ClosureTree工具。因为它目前只是在本地进行试验,所以我不太担心性能。很好,有相关父母的基础模型狗也可以。在闭包树中,您可以添加一个稍后的点,该点将充当缓存。这就是所有不同层次结构树解决方案(嵌套集、相邻列表、闭包树)的用途。在闭包树中,您将为每个狗添加新根,并通过将父节点作为子节点添加到树中来反转方向。即使是父母也会在该树的不同层次上多次存在,这样你就可以在一个sql查询中读取任何狗的完整祖先行。@neongrau如果你真的不需要任何花哨的或非规范化的东西来拉出整个树,PostgreSQL支持递归的
查询。很高兴也不同意你的意见;)STI很好,也很简单,但是当您需要遍历一棵树时,对于祖先中的每个级别(妈妈和爸爸),您都会遇到一个n+2 sql查询问题。因此,对于曾祖父母,您已经在使用n+2+4+8 sql查询来呈现家谱了。站点性能将不存在。所有内容都可以缓存。你可以创建一个方法来加载ID的嵌套,缓存它并让迭代器使用它。我确实明白neongrau关于性能的观点,我将研究用于重构的便捷ClosureTree工具。自从