From c3a26c592ca99e92056ae46328ca69336e400882 Mon Sep 17 00:00:00 2001 From: OZAWA Sakuro Date: Sat, 9 Mar 2013 15:37:26 +0900 Subject: [PATCH] Preserve magic comments and content encoding of copied migrations. During insertion of "# This migration comes from ... " comment at the beginning of a migration, presence of magic comment was not considered. --- activerecord/CHANGELOG.md | 4 ++++ activerecord/lib/active_record/migration.rb | 15 +++++++++++--- activerecord/test/cases/migration_test.rb | 20 +++++++++++++++++++ .../magic/1_currencies_have_symbols.rb | 12 +++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 activerecord/test/migrations/magic/1_currencies_have_symbols.rb diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 63d5bbb9ee78d..49f7b03464162 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 4.0.0 (unreleased) ## +* When copying migrations, preserve their magic comments and content encoding. + + *OZAWA Sakuro* + * Fix ActiveRecord `subclass_from_attrs` when `eager_load` is false. It cannot find subclass because all classes are loaded automatically when it needs. diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 3d71b784e7fae..5d7762ec3adc4 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -634,8 +634,17 @@ def copy(destination, sources, options = {}) source_migrations = ActiveRecord::Migrator.migrations(path) source_migrations.each do |migration| - source = File.read(migration.filename) - source = "# This migration comes from #{scope} (originally #{migration.version})\n#{source}" + source = File.binread(migration.filename) + inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n" + if /\A#.*\b(?:en)?coding:\s*\S+/ =~ source + # If we have a magic comment in the original migration, + # insert our comment after the first newline(end of the magic comment line) + # so the magic keep working. + # Note that magic comments must be at the first line(except sh-bang). + source[/\n/] = "\n#{inserted_comment}" + else + source = "#{inserted_comment}#{source}" + end if duplicate = destination_migrations.detect { |m| m.name == migration.name } if options[:on_skip] && duplicate.scope != scope.to_s @@ -649,7 +658,7 @@ def copy(destination, sources, options = {}) old_path, migration.filename = migration.filename, new_path last = migration - File.open(migration.filename, "w") { |f| f.write source } + File.binwrite(migration.filename, source) copied << migration options[:on_copy].call(scope, migration, old_path) if options[:on_copy] destination_migrations << migration diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 6f90500189bae..f8afb7c591b43 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -738,6 +738,26 @@ def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_fu clear end + def test_copying_migrations_preserving_magic_comments + ActiveRecord::Base.timestamped_migrations = false + @migrations_path = MIGRATIONS_ROOT + "/valid" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"}) + assert File.exists?(@migrations_path + "/4_currencies_have_symbols.bukkits.rb") + assert_equal [@migrations_path + "/4_currencies_have_symbols.bukkits.rb"], copied.map(&:filename) + + expected = "# coding: ISO-8859-15\n# This migration comes from bukkits (originally 1)" + assert_equal expected, IO.readlines(@migrations_path + "/4_currencies_have_symbols.bukkits.rb")[0..1].join.chomp + + files_count = Dir[@migrations_path + "/*.rb"].length + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/magic"}) + assert_equal files_count, Dir[@migrations_path + "/*.rb"].length + assert copied.empty? + ensure + clear + end + def test_skipping_migrations @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" @existing_migrations = Dir[@migrations_path + "/*.rb"] diff --git a/activerecord/test/migrations/magic/1_currencies_have_symbols.rb b/activerecord/test/migrations/magic/1_currencies_have_symbols.rb new file mode 100644 index 0000000000000..c066c068c2831 --- /dev/null +++ b/activerecord/test/migrations/magic/1_currencies_have_symbols.rb @@ -0,0 +1,12 @@ +# coding: ISO-8859-15 + +class CurrenciesHaveSymbols < ActiveRecord::Migration + def self.up + # We use ¤ for default currency symbol + add_column "currencies", "symbol", :string, :default => "¤" + end + + def self.down + remove_column "currencies", "symbol" + end +end