Ruby-GetText-Packageだけというわけではないですが、app/controllers/application.rbで何かを行う1gemを使っているとrake gems:installで足りないgemをインストールできません。経験したことがあるけど別に手動でインストールすればいいやということで、おそらく、わりとうやむやにされていることが多い問題ではないでしょうか。
例えば、Ruby-GetText-Packageだと以下のようにapp/controllers/application.rbを変更する必要があります。
class ApplicationController < ActionController::Base
init_gettext "blog"
end
Ruby-GetText-Packageのgemがない場合は「init_gettext」が定義されていないため「NameError」が発生します。そのため、rake gems:installをしようとすると以下のように失敗してしまいます。
% rake gems:install
(in /tmp/blog)
rake aborted!
undefined method `init_gettext' for ApplicationController:Class
(See full trace by running task with --trace)
これを回避するために「足りないgemがあるときはinit_gettextを使わない」という方法があります。 あまりきれいな方法ではありませんが、紹介します。
class ApplicationController < ActionController::Base
if Rails.configuration.gems.reject {|gem| gem.loaded?}.empty?
init_gettext "blog"
end
end
もし、config/environment.rbでconfig.active_record.observersを指定しているなどして、app/model/以下も読み込まれるのであれば、ダミーのN_を定義しておくとよいでしょう。
class ApplicationController < ActionController::Base
if Rails.configuration.gems.reject {|gem| gem.loaded?}.empty?
init_gettext "blog"
else
class ActiveRecord::Base
def self.N_(*args); end
end
end
end
これでRuby-GetText-Packageを使っているときでもrake gems:installが動くようになります。
% rake gems:install
(in /tmp/blog)
gem install gettext
Bulk updating Gem source index for: http://gems.rubyforge.org/
Successfully installed gettext-1.93.0
1 gem installed
Installing ri documentation for gettext-1.93.0...
Installing RDoc documentation for gettext-1.93.0...
以下、「足りないgemがあるとき」の判断方法について少し書いてみます。
足りないgemがあるとき
Railsでは「足りないgemがあるかどうか」を示すAPIを提供しているのはRails::Initializerです。ただ、残念ながらconfig/environment.rbの中で作ったRails::Initializerはどこにも保存されていないので、無理やり引っ張り出す必要があります。具体的には以下のようなコードになります。
initializer = nil
ObjectSpace.each_object(Rails::Initializer) do |object|
initializer = object
break
end
initializer.gems_dependencies_loaded
しかし、この方法ではRails::InitializerがGCされてしまっていると動きません2。
また、ObjectSpaceはできれば使いたくないものです。そのため、もう少し安全で、何をしているのかがまだわかりそうな方法の方がよさそうです。そのための「足りないgemがあるかどうか」を判断する方法が以下のようになるというわけです。
Rails.configuration.gems.reject {|gem| gem.loaded?}.empty?
ただ、この方法はRails 2.1.2(や2008-10-30でのmaster)では動きますが、もし、Rails内部の「足りないgemがあるかどうか」を判断する方法が変わった場合は動かなくなる可能性もあります。 「あまりきれいな方法ではありませんが」と書いたのはこのためです。
まとめ
Ruby-GetText-Packageを使っている場合でもrake gem:installを利用する方法を紹介しました。
同じような問題は他のライブラリでも起こりうると思うので、そのような場合も同じように問題を回避できると思います。