aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/migration.rb21
-rw-r--r--activerecord/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb9
-rw-r--r--activerecord/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb12
-rw-r--r--activerecord/test/fixtures/migrations_with_duplicate/3_foo.rb7
-rw-r--r--activerecord/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb12
-rw-r--r--activerecord/test/migration_test.rb6
6 files changed, 63 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 90984b080b..bf4f9aa530 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -2,6 +2,12 @@ module ActiveRecord
class IrreversibleMigration < ActiveRecordError#:nodoc:
end
+ class DuplicateMigrationVersionError < ActiveRecordError#:nodoc:
+ def initialize(version)
+ super("Multiple migrations have the version number #{version}")
+ end
+ end
+
# Migrations can manage the evolution of a schema used by several physical databases. It's a solution
# to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to
# push that change to other developers and to the production server. With migrations, you can describe the transformations
@@ -209,15 +215,22 @@ module ActiveRecord
private
def migration_classes
- migrations = migration_files.collect do |migration_file|
+ migrations = migration_files.inject([]) do |migrations, migration_file|
load(migration_file)
version, name = migration_version_and_name(migration_file)
- [ version.to_i, migration_class(name) ]
+ assert_unique_migration_version(migrations, version.to_i)
+ migrations << [ version.to_i, migration_class(name) ]
end
-
+
down? ? migrations.sort.reverse : migrations.sort
end
-
+
+ def assert_unique_migration_version(migrations, version)
+ if !migrations.empty? && migrations.transpose.first.include?(version)
+ raise DuplicateMigrationVersionError.new(version)
+ end
+ end
+
def migration_files
files = Dir["#{@migrations_path}/[0-9]*_*.rb"].sort_by do |f|
migration_version_and_name(f).first.to_i
diff --git a/activerecord/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb b/activerecord/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb
new file mode 100644
index 0000000000..009729b330
--- /dev/null
+++ b/activerecord/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb
@@ -0,0 +1,9 @@
+class PeopleHaveLastNames < ActiveRecord::Migration
+ def self.up
+ add_column "people", "last_name", :string
+ end
+
+ def self.down
+ remove_column "people", "last_name"
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb b/activerecord/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb
new file mode 100644
index 0000000000..ac5918f02a
--- /dev/null
+++ b/activerecord/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb
@@ -0,0 +1,12 @@
+class WeNeedReminders < ActiveRecord::Migration
+ def self.up
+ create_table("reminders") do |t|
+ t.column :content, :text
+ t.column :remind_at, :datetime
+ end
+ end
+
+ def self.down
+ drop_table "reminders"
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/fixtures/migrations_with_duplicate/3_foo.rb b/activerecord/test/fixtures/migrations_with_duplicate/3_foo.rb
new file mode 100644
index 0000000000..916fe580fa
--- /dev/null
+++ b/activerecord/test/fixtures/migrations_with_duplicate/3_foo.rb
@@ -0,0 +1,7 @@
+class Foo < ActiveRecord::Migration
+ def self.up
+ end
+
+ def self.down
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb b/activerecord/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb
new file mode 100644
index 0000000000..21c9ca5328
--- /dev/null
+++ b/activerecord/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb
@@ -0,0 +1,12 @@
+class InnocentJointable < ActiveRecord::Migration
+ def self.up
+ create_table("people_reminders", :id => false) do |t|
+ t.column :reminder_id, :integer
+ t.column :person_id, :integer
+ end
+ end
+
+ def self.down
+ drop_table "people_reminders"
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/migration_test.rb b/activerecord/test/migration_test.rb
index 56d5e12090..9c5c2285b7 100644
--- a/activerecord/test/migration_test.rb
+++ b/activerecord/test/migration_test.rb
@@ -408,5 +408,11 @@ if ActiveRecord::Base.connection.supports_migrations?
ActiveRecord::Base.table_name_suffix = ''
Reminder.reset_table_name
end
+
+ def test_migrator_with_duplicates
+ assert_raises(ActiveRecord::DuplicateMigrationVersionError) do
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil)
+ end
+ end
end
end