diff options
author | Yves Senn <yves.senn@gmail.com> | 2014-06-11 08:47:53 +0200 |
---|---|---|
committer | Yves Senn <yves.senn@gmail.com> | 2014-06-26 22:03:49 +0200 |
commit | acd0287dc18a3fbba6fa4301cb31a7aecd22922b (patch) | |
tree | 7ed2f4dc1d3b9d21772f638f390b876e62512f49 /activerecord | |
parent | 6955d864ceb0ba994ef4fb4c5e866463f247944b (diff) | |
download | rails-acd0287dc18a3fbba6fa4301cb31a7aecd22922b.tar.gz rails-acd0287dc18a3fbba6fa4301cb31a7aecd22922b.tar.bz2 rails-acd0287dc18a3fbba6fa4301cb31a7aecd22922b.zip |
fk: support for on_update
Diffstat (limited to 'activerecord')
7 files changed, 46 insertions, 19 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb index aad4431910..b896bd25e4 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb @@ -24,7 +24,8 @@ ADD CONSTRAINT #{quote_column_name(o.name)} FOREIGN KEY (#{quote_column_name(o.column)}) REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)}) SQL - sql << " #{action_sql(o.on_delete)}" if o.on_delete + sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete + sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update sql end @@ -101,7 +102,7 @@ FOREIGN KEY (#{quote_column_name(o.column)}) options.include?(:default) && !(options[:null] == false && options[:default].nil?) end - def action_sql(action = "DELETE", dependency) + def action_sql(action, dependency) case dependency when :nullify then "ON #{action} SET NULL" when :cascade then "ON #{action} CASCADE" diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 2d6cf2427c..2e47e68754 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -41,6 +41,10 @@ module ActiveRecord def on_delete options[:on_delete] end + + def on_update + options[:on_update] + end end # Represents the schema of an SQL table in an abstract way. This class diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 3f72e35bb5..18e73b0200 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -654,7 +654,8 @@ module ActiveRecord column: options[:column], primary_key: primary_key, name: foreign_key_name(from_table, options), - on_delete: options.fetch(:on_delete, nil) + on_delete: options[:on_delete], + on_update: options[:on_update] } at = create_alter_table from_table at.add_foreign_key to_table, options diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index f3b7fe172e..868181e677 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -530,17 +530,22 @@ module ActiveRecord primary_key: row['primary_key'] } - if create_table_info =~ /CONSTRAINT #{quote_column_name(row['name'])} FOREIGN KEY .* REFERENCES .* ON DELETE (CASCADE|SET NULL|RESTRICT)/ - options[:on_delete] = case $1 - when 'CASCADE' then :cascade - when 'SET NULL' then :nullify - end - end + options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE") + options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE") ForeignKeyDefinition.new(table_name, row['to_table'], options) end end + def extract_foreign_key_action(structure, name, action) # :nodoc: + if structure =~ /CONSTRAINT #{quote_column_name(name)} FOREIGN KEY .* REFERENCES .* ON #{action} (CASCADE|SET NULL|RESTRICT)/ + case $1 + when 'CASCADE'; :cascade + when 'SET NULL'; :nullify + end + end + end + # Maps logical Rails types to MySQL-specific data types. def type_to_sql(type, limit = nil, precision = nil, scale = nil) case type.to_s diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index bf87395ef1..7ffbe4434f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -450,7 +450,7 @@ module ActiveRecord def foreign_keys(table_name) fk_info = select_all <<-SQL -SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confdeltype AS dependency +SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete FROM pg_constraint c JOIN pg_class t1 ON c.conrelid = t1.oid JOIN pg_class t2 ON c.confrelid = t2.oid @@ -470,12 +470,17 @@ ORDER BY c.conname primary_key: row['primary_key'] } - options[:on_delete] = case row['dependency'] - when 'c'; :cascade - when 'n'; :nullify - when 'r'; :restrict - end - ForeignKeyDefinition.new(table_name, row["to_table"], options) + options[:on_delete] = extract_foreign_key_action(row['on_delete']) + options[:on_update] = extract_foreign_key_action(row['on_update']) + ForeignKeyDefinition.new(table_name, row['to_table'], options) + end + end + + def extract_foreign_key_action(specifier) # :nodoc: + case specifier + when 'c'; :cascade + when 'n'; :nullify + when 'r'; :restrict end end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index cdbb374510..9b46f7751b 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -226,6 +226,7 @@ HEADER 'primary_key: ' + foreign_key.primary_key.inspect, 'name: ' + foreign_key.name.inspect ] + parts << ('on_update: ' + foreign_key.on_update.inspect) if foreign_key.on_update parts << ('on_delete: ' + foreign_key.on_delete.inspect) if foreign_key.on_delete ' ' + parts.join(', ') diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index f391e9ef41..c69fc18d82 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -126,6 +126,16 @@ module ActiveRecord assert_equal :nullify, fk.on_delete end + def test_add_foreign_key_with_on_update + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :nullify + + foreign_keys = @connection.foreign_keys("astronauts") + assert_equal 1, foreign_keys.size + + fk = foreign_keys.first + assert_equal :nullify, fk.on_update + end + def test_remove_foreign_key_inferes_column @connection.add_foreign_key :astronauts, :rockets @@ -155,11 +165,11 @@ module ActiveRecord assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "id", name: "fk_name"$}, output end - def test_schema_dumping_on_delete_option - @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :nullify + def test_schema_dumping_on_delete_and_on_update_options + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :nullify, on_update: :cascade output = dump_table_schema "astronauts" - assert_match %r{\s+add_foreign_key "astronauts",.+on_delete: :nullify$}, output + assert_match %r{\s+add_foreign_key "astronauts",.+on_update: :cascade,.+on_delete: :nullify$}, output end class CreateCitiesAndHousesMigration < ActiveRecord::Migration |