Railsの凍結とmongrel.rbのパッチ

Railsは日々コードがメンテナンスされており、バージョンの遷移が非常に速い。私なんぞRails 1.2から勉強を初めた若輩だが、現在のRailsのバージョンは既に2.3だという。
このような状況の中で正しいバージョンのRailsを使ってアプリケーションを動かすために、作成したアプリケーションが依存するRailsのバージョンを凍結(freeze)する機構が備わっている。

具体的にはアプリケーションのルートからrake rails:freezeタスクを使って特定のバージョンのRailsを必ず使うようにアプリケーションに指示できるのだ。

  • 最新のRailsのバージョンを使って凍結する
rake rails:freeze:edge
: 私のようにサーバに接続できない環境の場合、rails:freeze:edgeは失敗する
  • 現在gemとしてインストールされているRailsを使って凍結する
E:\www\addressbook>rake rails:freeze:gems
(in E:/www/addressbook)
Freezing to the gems for Rails 2.2.2
rm -rf vendor/rails
mkdir -p vendor/rails
cd vendor/rails
Unpacked gem: 'E:/www/addressbook/vendor/rails/activesupport-2.2.2'
mv activesupport-2.2.2 activesupport
Unpacked gem: 'E:/www/addressbook/vendor/rails/activerecord-2.2.2'
mv activerecord-2.2.2 activerecord
Unpacked gem: 'E:/www/addressbook/vendor/rails/actionpack-2.2.2'
mv actionpack-2.2.2 actionpack
Unpacked gem: 'E:/www/addressbook/vendor/rails/actionmailer-2.2.2'
mv actionmailer-2.2.2 actionmailer
Unpacked gem: 'E:/www/addressbook/vendor/rails/activeresource-2.2.2'
mv activeresource-2.2.2 activeresource
Unpacked gem: 'E:/www/addressbook/vendor/rails/rails-2.2.2'
cd -

具体的には{RAILS_ROOT}/vendor/rails/に対象のRailsパッケージがコピーされるという訳だ。(UNIX環境の場合は、symlinkかもしれない) 
逆を言えばRailsアプリケーションはその起動時に"{RAILS_ROOT}/vendor/rails"が存在しているかどうかをまず判定し、あればそこにコピー(又はリンク)されているRailsを使うようになる。

さて、前エントリのパッチ"add_prefix_option_to_script_server_for_mongrel.patch"が指していたディレクトリだが

railties/lib/commands/servers/mongrel.rb

これは正にRailsアプリケーションが優先して実行するスクリプトのディレクトリであり、パッチを充てたスクリプトをここにコピーしておくことで、gemでインストールされた元々のソースコードSVNやgitと同期しているコードを汚さなくて済むという訳だ。

この辺も実に良くできているよなぁ。

  • 閑話休題

#10674 add_prefix_option_to_script_server_for_mongrel.patch - Rails Trac - Trac
このパッチ、diffが公開されていないんだが、Railsの決まりとしてはどうやってパッチ当てればいいんだろうと

...思ったのだが解った。Tracのページは下に「Plain Text」又は「Original Format」のリンクがあるんで、ここから.patch形式のファイルをダウンロードできる。

ダウンロードしたadd_prefix_option_to_script_server_for_mongrel.patch

Index: railties/lib/commands/servers/mongrel.rb
===================================================================
--- railties/lib/commands/servers/mongrel.rb	(revision 8526)
+++ railties/lib/commands/servers/mongrel.rb	(working copy)
@@ -13,12 +13,14 @@
   :ip          => "0.0.0.0",
   :environment => (ENV['RAILS_ENV'] || "development").dup,
   :detach      => false,
-  :debugger    => false
+  :debugger    => false,
+  :prefix      => nil
 }
 
 ARGV.clone.options do |opts|
   opts.on("-p", "--port=port", Integer, "Runs Rails on the specified port.", "Default: 3000") { |v| OPTIONS[:port] = v }
   opts.on("-b", "--binding=ip", String, "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
+  opts.on("-P", "--prefix=path", String, "Runs Rails app with a URL prefix (path).", "Default: none") { |v| OPTIONS[:prefix] = v }
   opts.on("-d", "--daemon", "Make server run as a Daemon.") { OPTIONS[:detach] = true }
   opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true }
   opts.on("-e", "--environment=name", String,
@@ -41,6 +43,7 @@
   "-e", OPTIONS[:environment],
   "-P", "#{RAILS_ROOT}/tmp/pids/mongrel.pid"
 ]
+parameters << "--prefix=#{OPTIONS[:prefix]}" unless OPTIONS[:prefix].blank?
 
 if OPTIONS[:detach]
   `mongrel_rails #{parameters.join(" ")} -d`

これは見事にdiff形式なんで、patchコマンドが使える環境であれば、該当のディレクトリにコピーして直接patchを実行すればOKだ。
なお、TortoiseSVNがインストールされている環境であれば、同TortoiseMergeを使うことで差分をプレビューしながらパッチを当てることもできる。

おーー、便利だねこりゃ。


今日のエントリで参考にさせて頂いたURL
Tiger Technologies Freezing Rails
EdgeRails in Ruby on Rails
Rails スクリプトの実行のメカニズム - ヽ( ・∀・)ノくまくまー(2006-02-24)