submoduleを使ってるプロジェクトのconfig/deploy.rb

gitのsubmoduleを使っているプロジェクトをCapistranoでデプロイしようとすると、submoduleで参照している部分は取得されないので、load_missing_constantとかの実行時にエラーになります。なので、submoduleも取ってきてねと設定する必要があります。

http://github.com/guides/deploying-with-capistrano で見つけたのが、以下の一行をconfig/deploy.rbに追加するだけっす。

set :git_enable_submodules, 1

gemcutterの設定をするcapistranoのタスク

gemcutterにgemを移したことで、そのgemを使えるようにデプロイ先のgemコマンドでgemcutterを使えるようにするためのタスクと、デプロイとは無関係にrake gems:install を実行するタスクを書きました。


cap gems:gemcutter

gemcutterの設定を行って、

cap gems:install

で、config/environment.rb で設定しているgemを一気にインストールします。まあ単にrake gems:install してるだけなんですけどね。

Module#unloadableメソッド

developmentモードで動かすと、自作pluginのviewに対してアクセスすると初回は問題ないが、2度目にアクセスすると
A copy of ApplicationController has been removed from the module tree but is still active!
などというメッセージとともにArgumentErrorが発生する。production環境だと発生しない。今のところ原因がよくわからない。
(追記)
http://d.hatena.ne.jp/tomisima/20090126/1232994598
に書いてあるようにcontrollerでunloadableを呼ぶとエラーは起きなくなる。つか公式サイトのプラグイン作成チュートリアルにも書いてあった。ちゃんと読もう > 自分

A copy of ApplicationController has been removed from the module tree but is still active!

っていうエラーは、プラグインでApplicationControllerが存在することを前提としたコントローラを作って、developmentモードで動かした場合、1度目のアクセスでは必要なコントローラ群がロードされるけど、そのコントローラへの2回目のアクセスでは、ApplicationControllerは再ロードされ、古いApplicationControllerクラス(Classクラスのインスタンス)は破棄されて使えないはずなんだけど、リロード対象外のプラグインにあるコントローラがそれを参照しているので、「その古いクラスはもうリロードされてるからそいつを参照している奴がいるのはおかしいよ」と言ってるようです。

なので、unloadableメソッドで自身をアンロード可能にしておいて、developmentモードで2回目のアクセスがあったとき?にアンロード/ロードをすることによってクラスを作り直して上記のエラーが出ないようにする必要がある訳です。実際unloadableメソッドの呼び出しと一緒にログを書いておくと振るまいが分かると思います。

class PluginEmbeddedController < ApplicationController
  unloadable

  logger.debug("#{self.name} loaded!")

id:maedanaさんが書かれている通り、RedmineのPlugin Tutorialにもその例が書いてありますね。
http://www.redmine.org/wiki/1/Plugin_Tutorial


P.S.
不思議なのは、このunloadableを設定したクラスを覚えておく explicitly_unloadable_constants というモジュール属性へのアクセスを行っている will_unload? メソッドへのアクセスがgrepで見つからないこと。activesupport, actionpack, rails のどこにもない。どこでこれ使ってるんだろう?
http://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb#481 なんだけど。うーむ謎。

GitHubのgem生成終了 => Gemcutter導入

GitHubがEngineYardからRackspaceへ移行した。この移行はかなりスムーズに実施されたのだが、Gemの自動作成機能がなくなった。

ということで、既に公開してあるgemは1年ほど公開してくれるらしいけど、今後GitHubはもうgemを生成してくれないので、僕が公開しているgemをgemcutter*1に移行してみました。

Gemcutterのアカウントを作成

http://gemcutter.org/ でメールアドレスとパスワードを入力して、Sign Up。確認のメールが来るのでそのメールにあるURLにアクセスすれば完了。

gemcutterをインストール

gem install gemcutter
gem tumble

これを実行するだけ。

$ sudo gem install gemcutter
Password:

========================================================================

           Thanks for installing Gemcutter! You can now run:

    gem tumble        use Gemcutter as your primary RubyGem source
    gem push          publish your gems for the world to use and enjoy
    gem migrate       take over your gem from RubyForge on Gemcutter
    gem owner         allow/disallow others to push to your gems

========================================================================

Successfully installed gemcutter-0.1.6
1 gem installed
Installing ri documentation for gemcutter-0.1.6...
Installing RDoc documentation for gemcutter-0.1.6...
$
$ gem tumble
Thanks for using Gemcutter!
Your gem sources are now:
- http://gemcutter.org
- http://gems.rubyforge.org
- http://gems.github.com

公開するGemをビルド

僕の場合はjewelerを使ってRakefileを書いてあるので、

rake build

すればオッケー。
http://github.com/akm/selectable_attr/blob/master/Rakefile

jewelerについてはこちらのエントリが詳しいです。
http://d.hatena.ne.jp/seiunsky/20090723/1248357767
http://technicalpickles.com/posts/craft-the-perfect-gem-with-jeweler/

Gemcutterに登録

gem push <gemファイル名>

ちなみに最初に実行したときには、こんなメッセージが出てきて、GemcutterSign Upしたメールアドレスとパスワードを訊かれます。

Enter your Gemcutter credentials. Don't have an account yet? Create one at http://gemcutter.org/sign_up
Email:   *********
Password:   
Signed in. Your api key has been stored in ~/.gemrc

簡単っすね。完了したらすぐにトップページ http://gemcutter.org/ のNew Gemsに載ってました。github.comだとちょっと待たなきゃいけなかったので、すぐ確認できるのがすごい。

*1:ひぐちカッターを真っ先に想像してしまった自分が情けない