如何将更新CASCADE添加到Rails-Postgres迁移中?

Tag*_*ag0 4 sql postgresql ruby-on-rails foreign-keys rails-migrations

我需要编写一个Rails迁移,该迁移将更新特定对象的uuid,然后通过将该ID作为外键存储的所有行进行CASCADE,如下所示:

alter table projects add constraint fk_league
foreign key (user_id) references users(id) on update cascade
Run Code Online (Sandbox Code Playgroud)

不幸的是,Rails似乎会自动生成约束:

fk_rails_e4348431a9
Run Code Online (Sandbox Code Playgroud)

我将如何编写上述sql来处理此问题?

mu *_*ort 6

大概您的迁移中有一个t.referencest.belongs_to某处:

t.references :user, :foreign_key => true
Run Code Online (Sandbox Code Playgroud)

t.references只是add_reference变相的电话。该add_reference文档没有说明有关该:foreign_key选项的值的任何有用信息,但是代码可以:

foreign_key_options = options.delete(:foreign_key)
#...
if foreign_key_options
  to_table = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
  add_foreign_key(table_name, to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
end
Run Code Online (Sandbox Code Playgroud)

因此,当您指定:foreign_key选项时,可以将其传递给基础add_foreign_key调用的选项哈希,并且具有一个:on_update选项:

:on_update
发生的动作ON UPDATE。有效值为:nullify:cascade:[sic]和:restrict

您想将原始t.references通话替换为以下内容:

t.references :user, :foreign_key => { :on_update => :cascade }
Run Code Online (Sandbox Code Playgroud)

如果您已经在生产中进行了所有设置,并且需要更改FK约束,那么我认为您需要手动解决问题:

  1. 添加迁移以删除原始约束并添加更新的约束:

    def up
      connection.execute(%q{
        alter table projects
        drop constraint fk_rails_e4348431a9
      })
      connection.execute(%q{
        alter table projects
        add constraint fk_rails_e4348431a9
        foreign key (user_id)
        references users(id)
        on update cascade
      })
    end
    def down
      # The opposite of the above...
    end
    
    Run Code Online (Sandbox Code Playgroud)

    您可能不需要保留Rails选择的约束名称,但是您也可以保留。

  2. 手动进行编辑,db/schema.rb以将上述内容添加:foreign_key => { :on_update => :cascade }到相应的t.references呼叫中。