From c0fb67c0f88bb81f525185a8dfceec6fb7cb298e Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Sat, 4 Mar 2006 18:46:51 +0000 Subject: [PATCH] Make migrations verbose git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3760 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 + activerecord/lib/active_record/migration.rb | 105 ++++++++++++++++++-- activerecord/test/migration_test.rb | 30 ++++++ 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index bf4dc24f5b..bcd5f0e430 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Make migrations verbose [Jamis Buck] + * Make counter_cache work with polymorphic belongs_to [Jamis Buck] * Fixed that calling HasOneProxy#build_model repeatedly would cause saving to happen #4058 [anna@wota.jp] diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 2192d588ad..262a1fb43e 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -159,16 +159,109 @@ module ActiveRecord # end # end # end + # + # == Controlling verbosity + # + # By default, migrations will describe the actions they are taking, writing + # them to the console as they happen, along with benchmarks describing how + # long each step took. + # + # You can quiet them down by setting ActiveRecord::Migration.verbose = false. + # + # You can also insert your own messages and benchmarks by using the #say_with_time + # method: + # + # def self.up + # ... + # say_with_time "Updating salaries..." do + # Person.find(:all).each do |p| + # p.salary = SalaryCalculator.compute(p) + # end + # end + # ... + # end + # + # The phrase "Updating salaries..." would then be printed, along with the + # benchmark for the block when the block completes. class Migration - class << self - def up() end - def down() end + @@verbose = true + cattr_accessor :verbose - private - def method_missing(method, *arguments, &block) + class << self + def up_using_benchmarks #:nodoc: + migrate(:up) + end + + def down_using_benchmarks #:nodoc: + migrate(:down) + end + + # Execute this migration in the named direction + def migrate(direction) + return unless respond_to?(direction) + + case direction + when :up then announce "migrating" + when :down then announce "reverting" + end + + result = nil + time = Benchmark.measure { result = send("real_#{direction}") } + + case direction + when :up then announce "migrated (%.4fs)" % time.real; write + when :down then announce "reverted (%.4fs)" % time.real; write + end + + result + end + + # Because the method added may do an alias_method, it can be invoked + # recursively. We use @ignore_new_methods as a guard to indicate whether + # it is safe for the call to proceed. + def singleton_method_added(sym) #:nodoc: + return if @ignore_new_methods + + begin + @ignore_new_methods = true + case sym + when :up, :down + klass = (class << self; self; end) + klass.send(:alias_method, "real_#{sym}", sym) + klass.send(:alias_method, sym, "#{sym}_using_benchmarks") + end + ensure + @ignore_new_methods = false + end + end + + def write(text="") + puts(text) if verbose + end + + def announce(message) + text = "#{name}: #{message}" + write "== %s %s" % [ text, "=" * (75 - text.length) ] + end + + def say(message, subitem=false) + write "#{subitem ? " ->" : "--"} #{message}" + end + + def say_with_time(message) + say(message) + result = nil + time = Benchmark.measure { result = yield } + say "%.4fs" % time.real, :subitem + result + end + + def method_missing(method, *arguments, &block) + say_with_time "#{method}(#{arguments.map { |a| a.inspect }.join(", ")})" do arguments[0] = Migrator.proper_table_name(arguments.first) unless arguments.empty? ActiveRecord::Base.connection.send(method, *arguments, &block) end + end end end @@ -225,7 +318,7 @@ module ActiveRecord next if irrelevant_migration?(version) Base.logger.info "Migrating to #{migration_class} (#{version})" - migration_class.send(@direction) + migration_class.migrate(@direction) set_schema_version(version) end end diff --git a/activerecord/test/migration_test.rb b/activerecord/test/migration_test.rb index 4fec71d39f..f4d6a2b7ef 100644 --- a/activerecord/test/migration_test.rb +++ b/activerecord/test/migration_test.rb @@ -6,10 +6,22 @@ require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders' if ActiveRecord::Base.connection.supports_migrations? class Reminder < ActiveRecord::Base; end + class ActiveRecord::Migration + class < 0 + PeopleHaveLastNames.message_count = 0 + + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + assert PeopleHaveLastNames.message_count > 0 + PeopleHaveLastNames.message_count = 0 + end + + def test_migrator_verbosity_off + PeopleHaveLastNames.verbose = false + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + assert PeopleHaveLastNames.message_count.zero? + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + assert PeopleHaveLastNames.message_count.zero? + end + def test_migrator_going_down_due_to_version_target ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0)