Skip to content

Commit

Permalink
Extract #build_add_column_definition
Browse files Browse the repository at this point in the history
Exposes AlterTable schema definition for adding new columns through new API,
and stores ddl on the schema definition. Refactors existing #add_column method to use
this as an intermediate method to build the create add_column definition.
  • Loading branch information
adrianna-chang-shopify committed Jul 28, 2022
1 parent f3339df commit e91b642
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
Expand Up @@ -26,6 +26,7 @@ def visit_AlterTable(o)
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
o.ddl = sql
end

def visit_ColumnDefinition(o)
Expand Down
Expand Up @@ -580,6 +580,7 @@ class AlterTable # :nodoc:
attr_reader :adds
attr_reader :foreign_key_adds, :foreign_key_drops
attr_reader :check_constraint_adds, :check_constraint_drops
attr_accessor :ddl

def initialize(td)
@td = td
Expand Down
Expand Up @@ -599,6 +599,24 @@ def drop_table(table_name, **options)
# # Ignores the method call if the column exists
# add_column(:shapes, :triangle, 'polygon', if_not_exists: true)
def add_column(table_name, column_name, type, **options)
add_column_def = build_add_column_definition(table_name, column_name, type, **options)
return unless add_column_def

execute(add_column_def.ddl)
end

def add_columns(table_name, *column_names, type:, **options) # :nodoc:
column_names.each do |column_name|
add_column(table_name, column_name, type, **options)
end
end

# Builds an AlterTable object for adding a column to a table.
#
# This definition object contains information about the column that would be created
# if the same arguments were passed to #add_column. See #add_column for information about
# passing a +table_name+, +column_name+, +type+ and other options that can be passed.
def build_add_column_definition(table_name, column_name, type, **options) # :nodoc:
return if options[:if_not_exists] == true && column_exists?(table_name, column_name)

if supports_datetime_with_precision?
Expand All @@ -607,15 +625,10 @@ def add_column(table_name, column_name, type, **options)
end
end

at = create_alter_table table_name
at.add_column(column_name, type, **options)
execute schema_creation.accept at
end

def add_columns(table_name, *column_names, type:, **options) # :nodoc:
column_names.each do |column_name|
add_column(table_name, column_name, type, **options)
end
alter_table = create_alter_table(table_name)
alter_table.add_column(column_name, type, **options)
schema_creation.accept(alter_table)
alter_table
end

# Removes the given columns from the table definition.
Expand Down
Expand Up @@ -10,6 +10,7 @@ def visit_AlterTable(o)
sql << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
sql << o.exclusion_constraint_adds.map { |con| visit_AddExclusionConstraint con }.join(" ")
sql << o.exclusion_constraint_drops.map { |con| visit_DropExclusionConstraint con }.join(" ")
o.ddl = sql
end

def visit_AddForeignKey(o)
Expand Down
17 changes: 17 additions & 0 deletions activerecord/test/cases/migration/schema_definitions_test.rb
Expand Up @@ -61,6 +61,23 @@ def test_build_create_index_definition_for_existing_index
connection.drop_table(:test) if connection.table_exists?(:test)
end
end

def test_build_add_column_definition
connection.create_table(:test)
add_col_td = connection.build_add_column_definition(:test, :foo, :string)

assert_match "ALTER TABLE", add_col_td.ddl

add_cols = add_col_td.adds
assert_equal 1, add_cols.size

add_col = add_cols.first.column
assert_equal "foo", add_col.name
assert add_col.type
assert add_col.sql_type
ensure
connection.drop_table(:test) if connection.table_exists?(:test)
end
end
end
end

0 comments on commit e91b642

Please sign in to comment.