モチベーション
rake db:migrate を実行するときに
ActiveRecord::ConnectionAdapters::Mysql2Adapter.initialize_schema_migrations_table がいったいどのようなタイミングで呼び出されるのか、知りたくなりました。
Rails 4.2.4 でのソースコードは https://github.com/rails/rails/blob/v4.2.4/activerecord/lib/active_record/migration.rb になるのですが、ちょっと追いづらい。
そこで prepend と byebug を使ってスタックトレースを表示してみることにしました。
実際のコード
ActiveSupport.on_load :active_record do
module ActiveRecord::ConnectionAdapters
module Mysql2AdapterExt
def initialize_schema_migrations_table
debugger
super
end
end
class Mysql2Adapter
prepend Mysql2AdapterExt
end
end
end
prepend を使わずに、オープンクラスを使っても良かったのかもしれませんが、その後の実行もできるように今回は prepend にしてみました。
実行結果
rake db:migrate を実行してみます。
[1, 10] in /Users/../config/initializers/ar_test.rb
1: ActiveSupport.on_load :active_record do
2: module ActiveRecord::ConnectionAdapters
3: module Mysql2AdapterExt
4: def initialize_schema_migrations_table
5: debugger
=> 6: super
7: end
8: end
9:
10: class Mysql2Adapter
(byebug)
無事に debugger を入れたところで止まります。ここで byebug の bt コマンドを使って、スタックトレースを表示してみます。
(byebug) bt
--> #0 ActiveRecord::ConnectionAdapters::Mysql2AdapterExt.initialize_schema_migrations_table at /Users/.../config/initializers/ar_test.rb:6
#1 ActiveRecord::Migrator.initialize(direction#Symbol, migrations#Array, target_version#NilClass) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/migration.rb:922
ͱ-- #2 Class.new(*args) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/migration.rb:820
#3 #<Class:ActiveRecord::Migrator>.up(migrations_paths#Array, target_version#NilClass) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/migration.rb:820
#4 #<Class:ActiveRecord::Migrator>.migrate(migrations_paths#Array, target_version#NilClass, &block#Proc) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/migration.rb:798
#5 ActiveRecord::Tasks::DatabaseTasks.migrate at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/tasks/database_tasks.rb:137
#6 block (2 levels) in <top (required)> at /Users/.../.rvm/gems/ruby-2.1.7@/gems/activerecord-4.2.4/lib/active_record/railties/databases.rake:44
ͱ-- #7 Proc.call(*args) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:240
#8 block in Rake::Task.execute(args#Rake::TaskArguments) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:240
ͱ-- #9 Array.each at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:235
#10 Rake::Task.execute(args#Rake::TaskArguments) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:235
#11 block in Rake::Task.invoke_with_call_chain(task_args#Rake::TaskArguments, invocation_chain#Rake::InvocationChain::EmptyInvocationChain) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:179
#12 MonitorMixin.mon_synchronize at /Users/.../.rvm/rubies/ruby-2.1.7@/lib/ruby/2.1.0/monitor.rb:211
#13 Rake::Task.invoke_with_call_chain(task_args#Rake::TaskArguments, invocation_chain#Rake::InvocationChain::EmptyInvocationChain) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:172
#14 Rake::Task.invoke(*args#Array) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/task.rb:165
#15 Rake::Application.invoke_task(task_string#String) at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:150
#16 block (2 levels) in Rake::Application.top_level at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:106
ͱ-- #17 Array.each at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:106
#18 block in Rake::Application.top_level at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:106
#19 Rake::Application.run_with_threads at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:115
#20 Rake::Application.top_level at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:100
#21 block in Rake::Application.run at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:78
#22 Rake::Application.standard_exception_handling at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:176
#23 Rake::Application.run at /Users/.../.rvm/gems/ruby-2.1.7@/gems/rake-10.4.2/lib/rake/application.rb:75
#24 <main> at /Users/.../bin/rake:4
(byebug)
よく理解できました。あとは byebug の c コマンドを使えば、そのまま実行を継続できます。