class RuboCop::Cop::Discourse::NoAddReferenceOrAliasesActiveRecordMigration

The methods:

in ActiveRecord migrations are magic, and they all do some unexpected things in the background. For example, by default add_reference adds an index at the same time, but not concurrently, which is a nightmare for large tables.

Instead, inside a disable_ddl_transaction! migration we should create the new column (with any defaults and options required) and the index concurrently using hand-written SQL. This also allows us to handle IF NOT EXISTS cases, which enable re-runnable migrations. Also we can pick a better name for the index at the same time.

@example

# bad def up

add_reference :posts, :image_upload
# or add_belongs_to :posts, :image_upload
# or t.references :image_upload when doing create_table do |t|
# or t.belongs_to :image_upload when doing create_table do |t|

end

# good disable_ddl_transaction! def up

execute <<~SQL
  ALTER TABLE posts
  ADD COLUMN IF NOT EXISTS image_upload_id bigint
SQL

execute <<~SQL
  CREATE INDEX CONCURRENTLY IF NOT EXISTS
  index_posts_on_image_upload_id ON posts USING btree (image_upload_id)
SQL

end

Constants

MSG

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/discourse/no_add_reference_active_record_migrations.rb, line 72
def on_send(node)
  return if [
    using_add_reference?(node),
    using_add_belongs_to?(node),
    using_t_references?(node),
    using_t_belongs_to?(node)
  ].none?
  add_offense(node, message: MSG)
end