2016-09-18 36 views
2

自加入我自联接称为模型部分:导轨 - 在PostgreSQL

class Section < ApplicationRecord 
    belongs_to :offer 
    # Self joins: 
    has_many :child_sections, class_name: "Section", foreign_key: "parent_section_id" 
    belongs_to :parent_section, class_name: "Section", optional: true 
end 

与移民文件:

class CreateSections < ActiveRecord::Migration[5.0] 
    def change 
    create_table :sections do |t| 
     t.string :name 
     t.references :offer, foreign_key: true 

     t.references :parent_section, foreign_key: true 
     t.timestamps 
    end 
    end 
end 

使用MySQL被罚款,但后来我放弃了数据库,改变了他们postresql(所以他们是heroku友好),并创建新的。尝试rails db:migrate后有错误说:

StandardError: An error has occurred, this and all later migrations canceled: 

PG::UndefinedTable: ERROR: relation "parent_sections" does not exist 

可能发生了什么? mysql和postgresql中的自连接有什么区别吗?

回答

3

t.references电话:

t.references :parent_section, foreign_key: true 

会尽量做两件事情在PostgreSQL:

  1. 添加一个整数列叫parent_section_id
  2. 在数据库中添加一个foreign key constraint以确保参照完整性(即确保parent_section_id参考部分存在的值)。

您的问题与。对于t.references :parent_section的FK会是什么样子:

parent_section_id integer references parent_sections(id) 

,因为它使用了标准的Rails命名约定,这就是你的parent_sections误差的来源。您可以指定目标表的FK约束,就像你可以提供给:class_namebelongs_to

t.references :parent_section, :foreign_key => { :to_table => :sections } 

此修复程序触发下一个问题:你不能创建一个FK到不存在的表和直到create_table :sections块完成执行,sections才会存在。

对于这个问题,有两种常见的解决方案:

  1. 与所有列创建表,然后添加FK约束。像这样的事情在你的迁移:

    create_table :sections do |t| 
        t.string :name 
        t.references :offer, foreign_key: true 
        t.references :parent_section 
        t.timestamps 
    end 
    add_foreign_key :sections, :sections, :column => :parent_section_id 
    
  2. 没有引用列(parent_section_id)创建表,然后添加引用列和之后的FK。像这样的事情在你的迁移:

    create_table :sections do |t| 
        t.string :name 
        t.references :offer, foreign_key: true 
        t.timestamps 
    end 
    change_table :sections do |t| 
        t.references :parent_section, :foreign_key => { :to_table => :sections } 
    end 
    
+0

真是一个伟大的答案!我一回家就会尝试。我想补充的是,在执行db:reset之后,错误消失了,但仍然无法在之后进行迁移。 – Ancinek

+1

@Ancinek确保接受答案,如果这对你有用 - 这是一个很好的做法和SO的“好做”接受解决你的问题的答案。通过这样做,您既奖励向您提供解决方案**的用户,又让该社区知道问题已解决。 –