# frozen_string_literal: false # @!parse # class ActiveRecord::Migration # # Rename a foreign key # # # # @param [#to_s] table (nil) The qualified name of the table # # @param [#to_s] reference (nil) The qualified name of the reference table # # @option options [#to_s] :name (nil) The current name of the foreign key # # @option options [#to_s] :to (nil) The new name for the foreign key # # @option options [Array<#to_s>] :columns ([]) The list of columns of the table # # @option options [#to_s] :column (nil) An alias for :columns for the case of single-column keys # # @option options [Array<#to_s>] :primary_key ([]) The list of columns of the reference table # # @yield [k] the block with the key's definition # # @yieldparam Object receiver of methods specifying the foreign key # # @return [void] # # # # You can rename the foreign key constraint identified by its explicit name: # # # # ```ruby # # rename_foreign_key :users, # # name: "user_roles_fk", # # to: "constraints.users_by_roles_fk" # # ``` # # # # The key can also be found in the database by table/reference/columns/pk # # # # ```ruby # # rename_foreign_key :users, :roles, primary_key: "name", to: "user_roles" # # ``` # # # # If a new name is missed, then the name will be reset to the auto-generated one: # # # # ```ruby # # rename_foreign_key :users, "user_roles_fk" # # ``` # # # # The operation is always reversible. # def rename_foreign_key(table, reference, **options, &block); end # end module PGTrunk::Operations::ForeignKeys # # Definition for the `rename_foreign_key` operation # class RenameForeignKey < Base # The name can be looked for in the database. # This is necessary because the name generated by `rails` inside the table # is different from the name generated by the `add_foreign_key`. after_initialize { self.name = current_name if name.blank? } # Reset the name to default when `to:` option is missed or set to `nil` after_initialize { self.new_name = generated_name if new_name.blank? } validates :new_name, presence: true validates :if_exists, :if_not_exists, :match, absence: true def to_sql(_version) <<~SQL.squish ALTER TABLE #{table.to_sql} RENAME CONSTRAINT #{name.name.inspect} TO #{new_name.name.inspect}; SQL end def invert self.class.new( **to_h, name: (new_name if custom_name?(new_name)), to: (name if name != current_name), ) end end end