rails2.1.0でgettextのエラー

$ ./script/server -b 127.0.0.1
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.1.0 application starting on http://127.0.0.1:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 127.0.0.1:3000
** Starting Rails with development environment...
Exiting
/Users/pistolfly/railsprojects/test/app/controllers/application.rb:7: undefined method `init_gettext' for ApplicationController:Class (NoMethodError)
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:215:in `load_without_new_constant_marking'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:215:in `load_file'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:354:in `new_constants_in'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:214:in `load_file'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:95:in `require_or_load'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:60:in `depend_on'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:456:in `require_dependency'
	from /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:18:in `define_dispatcher_callbacks'
	 ... 40 levels...
	from /Library/Ruby/Gems/1.8/gems/rails-2.1.0/lib/commands/server.rb:39
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `require'
	from ./script/server:3

とりあえずエラーが発生しているApplicationController(application.rb)のinit_gettextをコメントアウトしてmongrelを起動して、ページにアクセスすると、今度は以下のエラー。

  Status: 500 Internal Server Error
  undefined method `file_exists?' for #
    /Library/Ruby/Gems/1.8/gems/gettext-1.91.0/lib/gettext/rails.rb:281:in `render_file'
    /Library/Ruby/Gems/1.8/gems/gettext-1.91.0/lib/gettext/rails.rb:279:in `each'
    /Library/Ruby/Gems/1.8/gems/gettext-1.91.0/lib/gettext/rails.rb:279:in `render_file'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/rescue.rb:181:in `rescue_action_locally'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/rescue.rb:125:in `rescue_action'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/rescue.rb:203:in `perform_action_without_caching'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/caching/sql_cache.rb:13:in `perform_action'
    /Library/Ruby/Gems/1.8/gems/activerecord-2.1.0/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache'
    /Library/Ruby/Gems/1.8/gems/activerecord-2.1.0/lib/active_record/query_cache.rb:8:in `cache'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/caching/sql_cache.rb:12:in `perform_action'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:529:in `send'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:529:in `process_without_filters'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/filters.rb:569:in `process_without_session_management_support'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/session_management.rb:130:in `process'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/base.rb:389:in `process'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:149:in `handle_request'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:107:in `dispatch'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:104:in `synchronize'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:104:in `dispatch'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.1.0/lib/action_controller/dispatcher.rb:35:in `dispatch'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/rails.rb:76:in `process'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/rails.rb:74:in `synchronize'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/rails.rb:74:in `process'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:282:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `each'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/lib/mongrel/command.rb:212:in `run'
    /Library/Ruby/Gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:354:in `new_constants_in'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:502:in `load'
    /Library/Ruby/Gems/1.8/gems/rails-2.1.0/lib/commands/servers/mongrel.rb:64
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `require'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:509:in `require'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:354:in `new_constants_in'
    /Library/Ruby/Gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:509:in `require'
    /Library/Ruby/Gems/1.8/gems/rails-2.1.0/lib/commands/server.rb:39
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:27:in `require'
    ./script/server:3

対処方法は以下のページに。
rails2.0.2 → 2.1.0 に移行 - 夜の Discovery
Edge Rails and gettext: undefined method file_exists? (NoMethodError)
config/initializers/gettext.rbを作成する。
内容は以下。

require 'gettext/rails'
module ActionView
  class Base
    delegate :file_exists?, :to => :finder unless respond_to?(:file_exists?)
  end
end

config/initializers/gettext.rbにgettext/railsのrequireを書いたので、config/environment.rbから、gettext/railsの読み込みを削除。

# config/initializers/gettext.rbに移動
#require 'gettext/rails'

この問題は、Rails-2.0.xからRails-2.1.0でActionView::Base#file_exists? メソッドが ActionView::TemplateFinder#file_exists?に移ったことが原因らしい。
Ruby-GetText-1.92.0で対応済みなので、上記回避方法は不要となった。
Rails2.1以降では、environment.rbで、require 'gettext/rails'ではなく、config.gemを使う。

require 'gettext/rails'

ではなく、

Rails::Initializer.run do |config|
  :
  :
  config.gem "gettext", :lib => "gettext/rails"
end

Windows サービスを柔軟に管理するサービスマネージャの製作

Windows サービスを柔軟に管理するサービスマネージャの製作:パート1 - japan.internet.com デベロッパー
Windows サービスを柔軟に管理するサービスマネージャの製作:パート2 - japan.internet.com デベロッパー
AppDomain、AppDomainSetupの使用方法が分かるサンプルがある。

// create the service app domain
AppDomain svcDomain = null;
try
{
	AppDomainSetup setup = new AppDomainSetup();
	// use the process base directory as the new domain base and bin path
	setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
	setup.PrivateBinPath = setup.ApplicationBase;
	// use the assembly full name as friendly name
	setup.ApplicationName = asmName.FullName;
	// the base will be the shadow copy 'from' directory
	setup.ShadowCopyDirectories = setup.ApplicationBase;
	// enable shadow copying
	setup.ShadowCopyFiles = "true";
	// create the domain with no CAS evidence
	svcDomain = AppDomain.CreateDomain(asmName.FullName, null, setup);
}
catch (Exception ex)
{
	Logger.LogException(
		new ApplicationException(
			String.Format("Could not create an AppDomain for '{0}'; bypassing that assembly.", 
			asmName.FullName), ex));
	return;
}
// Get remote service handler
RemoteServiceHandler svc = null;
try
{
	// This call will actually create an instance
	// of the service handler in the service domain
	// and return a remoting proxy for us to act on.
	// This is important because we don't want to 
	// load any type info from the service assembly
	// into this assembly
	svc = (RemoteServiceHandler)  
		svcDomain.CreateInstanceFromAndUnwrap(
		svcDomain.BaseDirectory + "\\ServiceBroker.dll", 
		"ServiceBroker.RemoteServiceHandler");
}
catch (Exception ex)
{
	// unload domain
	AppDomain.Unload(svcDomain);
	Logger.LogException(
		new AssemblyLoadException(
			"Could not load ServiceBroker remote service handler, bypassing that file.",
		asmName.FullName, ex));
	return;
}

これは、被管理サービスの実行に使う新しいAppDomainをセットアップするコードです。AppDomainSetupオブジェクトを使用しているのは、AppDomain.CreateDomainのオーバーロードにはないオプションがあるためです。ここでは、ディレクトリプロパティを、現アプリケーションディレクトリを指し示すように設定することと、ファイルのシャドウコピーを作成するよう指示することが重要です。シャドウコピーを作成することによって、アセンブリがアプリケーションディレクトリでロックされることを防止できます。ここで例外がスローされることはまずないと思われますが、それでも、何が起こったかをログに記録するためと、スレッドを例外で終わらせないために、例外を正確にキャッチするようにしました。アプリケーションにユーザインタフェースがないときは、こうやって例外をキャッチし、ログに記録することをお勧めします。

postfixでサブミッションポートに対応する

Outbound Port 25 Blockingが導入されているISPからの接続でメールを送信できるようにするため、postfixがサブミッションポートでもListenするように設定した。
1. /etc/postfix/master.cf の以下の部分のコメントを外す。

#submission inet n      -       n       -       -       smtpd

2. 設定したら、postfixをリロード。

# /etc/init.d/postfix reload

3. ファイアウォールで587番ポートを開ける。

MAMPの環境にrubyのMySQLアダプタをインストールする

MAMPの環境でgem install mysqlを実行すると、以下のエラーになる。

$ sudo gem install mysql
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
	ERROR: Failed to build gem native extension.
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no
Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /Library/Ruby/Gems/1.8/gems/mysql-2.7/gem_make.out

MAMPのmysqlは、ヘッダファイル、ライブラリがデフォルトの/usr/local/lib、/usr/local/includeにないので、オプションを指定する必要がある。オプションはいろいろあるが、--with-mysql-configを使うと便利。
MySQL/Ruby

--with-mysql-config[=/path/to/mysql_config]
    mysql_config コマンドの結果からコンパイルパラメータを得ます。 

mysql_config コマンドにパスが通るように、.bash_profileなどで、PATHにMAMPのディレクトリを追加しておくか、--with-mysql-config=/Applications/MAMP/Library/bin/mysql_configを指定する。
ここでは、PATHを設定します。

export PATH=/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5/bin:/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin:$PATH

再度、インストール。

$ sudo gem install mysql -- --with-mysql-config
Building native extensions.  This could take a while...Successfully installed mysql-2.7
1 gem installed

OK。