Class: ActiveRecord::Migration
- Inherits:
-
Object
- Object
- ActiveRecord::Migration
- Defined in:
- lib/active_record/migration/active_migration_patch.rb
Overview
If you would like to use these methods in a Rails migration, make sure you add this require line at the top of your migration file:
require "active_migration_patch"
Direct Known Subclasses
Instance Method Summary collapse
-
#add_compound_foreign_key(from_table:, to_table:, from_columns:, to_columns:, name: nil, validate: true) ⇒ Object
Adds a compound foreign key based on the arguments passed in.
-
#add_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil, validate: true) ⇒ Object
Adds a foreign key based on the arguments passed in.
-
#compound_foreign_key_name(from_table:, to_table:, from_columns:, to_columns:) ⇒ Object
Returns a name for the foreign key constraint.
- #conditionally_add_index(table, columns, opts = {}) ⇒ Object
- #foreign_key_columns(to_table:, from_columns: nil, to_columns: nil) ⇒ Object
- #validate_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil) ⇒ Object
Instance Method Details
#add_compound_foreign_key(from_table:, to_table:, from_columns:, to_columns:, name: nil, validate: true) ⇒ Object
Adds a compound foreign key based on the arguments passed in. from_table: name of the table the fk constraint is on (symbol or string) to_table: name of the table the fk references (symbol or string) from_columns (optional): name of the fk column(s) in from_table; defaults to using the standard foreign key name for the to_table - e.g., "client_id" if the to_table is "clients" (symbol, string, or array of symbols and/or strings) to_columns (optional): name of the referenced column(s) in to_table; defaults to "id" (symbol, string, or array of symbols and/or strings) name (optional): name for the foreign key constraint If you pass in from_columns and to_columns, the columns should be ordered so the first references the first, the second references the second etc.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 82 def add_compound_foreign_key(from_table:, to_table:, from_columns:, to_columns:, name: nil, validate: true) name ||= compound_foreign_key_name( from_table: from_table, to_table: to_table, from_columns: from_columns, to_columns: to_columns ) ActiveRecord::Base.connection_pool.with_connection do |conn| conn.execute <<-END_OF_SQL ALTER TABLE #{from_table} ADD CONSTRAINT #{name} FOREIGN KEY (#{from_columns.join(",")}) REFERENCES #{to_table} (#{to_columns.join(",")}) #{"NOT VALID" unless validate} DEFERRABLE INITIALLY DEFERRED; END_OF_SQL end end |
#add_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil, validate: true) ⇒ Object
Adds a foreign key based on the arguments passed in. If organization_id is not already part of the from_columns, it adds it to both the from_columns and to_columns. The default foreign key name will use the same format we used in our data migrations to initially update all foreign keys to include organization_id. from_table: name of the table the fk constraint is on (symbol or string) to_table: name of the table the fk references (symbol or string) from_columns (optional): name of the fk column(s) in from_table; defaults to using the standard foreign key name for the to_table - e.g., "client_id" if the to_table is "clients" (symbol, string, or array of symbols and/or strings) to_columns (optional): name of the referenced column(s) in to_table; defaults to "id" (symbol, string, or array of symbols and/or strings) name (optional): name for the foreign key constraint If you pass in from_columns and to_columns, the columns should be ordered so the first references the first, the second references the second etc.
EXAMPLES:
add_org_scoped_foreign_key(from_table: :trustees, to_table: :clients)
add_org_scoped_foreign_key(
from_table: :advisors,
to_table: :users,
from_columns: :created_by_id
)
add_org_scoped_foreign_key(
from_table: :toys,
to_table: "factories",
from_columns: [:factory_id, "toy_category_id"]
to_columns: ["id", :toy_category_id]
)
41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 41 def add_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil, validate: true) from_columns, to_columns = foreign_key_columns(to_table: to_table, from_columns: from_columns, to_columns: to_columns) add_compound_foreign_key( from_table: from_table, to_table: to_table, from_columns: from_columns, to_columns: to_columns, name: name, validate: validate ) end |
#compound_foreign_key_name(from_table:, to_table:, from_columns:, to_columns:) ⇒ Object
Returns a name for the foreign key constraint. If the from_columns include organization_id, the name begins with "org_id_fk_"; otherwise, it starts with "compound_fk_".
104 105 106 107 108 109 110 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 104 def compound_foreign_key_name(from_table:, to_table:, from_columns:, to_columns:) from_columns = from_columns.map(&:to_s) to_columns = to_columns.map(&:to_s) prefix = from_columns.include?("organization_id") ? "org_id" : "compound" "#{prefix}_fk_#{::Digest::MD5.hexdigest([from_table.to_s, from_columns, to_table.to_s, to_columns].flatten.join("."))}" end |
#conditionally_add_index(table, columns, opts = {}) ⇒ Object
7 8 9 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 7 def conditionally_add_index(table, columns, opts = {}) add_index(table, columns, opts) unless index_exists?(table, columns, opts) end |
#foreign_key_columns(to_table:, from_columns: nil, to_columns: nil) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 112 def foreign_key_columns(to_table:, from_columns: nil, to_columns: nil) from_columns = from_columns.blank? ? [to_table.to_s.singularize.foreign_key] : Array(from_columns) to_columns = to_columns.blank? ? ["id"] : Array(to_columns) unless from_columns.map(&:to_s).include?("organization_id") from_columns << "organization_id" to_columns << "organization_id" end return from_columns, to_columns end |
#validate_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/active_record/migration/active_migration_patch.rb', line 53 def validate_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil) from_columns, to_columns = foreign_key_columns(to_table: to_table, from_columns: from_columns, to_columns: to_columns) name ||= compound_foreign_key_name( from_table: from_table, to_table: to_table, from_columns: from_columns, to_columns: to_columns ) ActiveRecord::Base.connection_pool.with_connection do |conn| conn.execute <<-END_OF_SQL ALTER TABLE #{from_table} VALIDATE CONSTRAINT #{name}; END_OF_SQL end end |