株式会社クリアコード > ククログ

ククログ


Ruby-GetText-Packageとrake gems:installの共存

Ruby-GetText-Packageだけというわけではないですが、app/controllers/application.rbで何かを行う*1gemを使っているとrake gems:installで足りないgemをインストールできません。経験したことがあるけど別に手動でインストールすればいいやということで、おそらく、わりとうやむやにされていることが多い問題ではないでしょうか。

例えば、Ruby-GetText-Packageだと以下のようにapp/controllers/application.rbを変更する必要があります。

1
2
3
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を使わない」という方法があります。 あまりきれいな方法ではありませんが、紹介します。

1
2
3
4
5
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_を定義しておくとよいでしょう。

1
2
3
4
5
6
7
8
9
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はどこにも保存されていないので、無理やり引っ張り出す必要があります。具体的には以下のようなコードになります。

1
2
3
4
5
6
initializer = nil
ObjectSpace.each_object(Rails::Initializer) do |object|
  initializer = object
  break
end
initializer.gems_dependencies_loaded

しかし、この方法ではRails::InitializerがGCされてしまっていると動きません*2

また、ObjectSpaceはできれば使いたくないものです。そのため、もう少し安全で、何をしているのかがまだわかりそうな方法の方がよさそうです。そのための「足りないgemがあるかどうか」を判断する方法が以下のようになるというわけです。

1
Rails.configuration.gems.reject {|gem| gem.loaded?}.empty?

ただ、この方法はRails 2.1.2(や2008-10-30でのmaster)では動きますが、もし、Rails内部の「足りないgemがあるかどうか」を判断する方法が変わった場合は動かなくなる可能性もあります。 「あまりきれいな方法ではありませんが」と書いたのはこのためです。

まとめ

Ruby-GetText-Packageを使っている場合でもrake gem:installを利用する方法を紹介しました。

同じような問題は他のライブラリでも起こりうると思うので、そのような場合も同じように問題を回避できると思います。

*1 もう少しいうと、読み込まれた時に実行される場所(例えばクラス定義の中)で何かを行う場合。メソッド定義の中などその場では実行されないものは関係ない。

*2 多くの場合はそんな状況にはならないでしょう

タグ: Ruby
2008-10-30

«前の記事: GaUnit 0.1.6リリース 最新記事 次の記事: Test::Unit 2.0.1リリース»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|