MerbでORMとしてDataMapperを使っている場合は、 コントローラのアクションが、以下のように仮引数でパラメータを受け取るようなデザインになっています。

   1    def show(id)
   2      @user = User.get(id)
   3      raise NotFound unless @user
   4      display @user
   5    end

このとき、Merbは、merb-action-argsというモジュールを使い、 仮引数idの名前をしらべ、Railsでいうところのparams[:id]の情報をもってきます。

merb-action-args は、以下のようにUnboundMethodの仮引数を取得します。

   1  def foo(id, bar); end
   2  method(:foo).get_args
   3  #=> [[[:id], [:bar]], []]

内部的には ruby2ruby を使っている模様。これはすごい。

See Also

posted by Png genki on Thu 20 Nov 2008 at 17:35

merb-genのサブコマンドには、resource, model, resource_controller, controllerという感じで、リソース版とそうではない版があるようなのですが、 違いが何なのかを調べてみました。

まずはmodel

   1  % merb-gen model foo
   2       (snip)
   3       [ADDED]  spec/models/foo_spec.rb
   4       [ADDED]  app/models/foo.rb

次はresource

   1  % merb-gen resource foo
   2       (snip)
   3       [ADDED]  spec/models/foo_spec.rb
   4       [ADDED]  app/models/foo.rb
   5       [ADDED]  spec/requests/foos_spec.rb
   6       [ADDED]  app/controllers/foos.rb
   7       [ADDED]  app/views/foos/index.html.erb
   8       [ADDED]  app/views/foos/show.html.erb
   9       [ADDED]  app/views/foos/edit.html.erb
  10       [ADDED]  app/views/foos/new.html.erb
  11       [ADDED]  app/helpers/foos_helper.rb

なるほど。resourceの方はRailsのscript/generate resourceのように、 コントローラやViewも作成してくれるようです。

ではcontrollerとresource_controllerの違いはなんでしょうか。 まずはcontroller

   1  % merb-gen controller foo
   2       (snip)
   3       [ADDED]  app/controllers/foo.rb
   4       [ADDED]  app/views/foo/index.html.erb
   5       [ADDED]  spec/requests/foo_spec.rb
   6       [ADDED]  app/helpers/foo_helper.rb

続いてresource_controller

   1  % merb-gen resource_controller foo
   2       (snip)
   3       [ADDED]  spec/requests/foo_spec.rb
   4       [ADDED]  app/controllers/foo.rb
   5       [ADDED]  app/views/foo/index.html.erb
   6       [ADDED]  app/views/foo/show.html.erb
   7       [ADDED]  app/views/foo/edit.html.erb
   8       [ADDED]  app/views/foo/new.html.erb
   9       [ADDED]  app/helpers/foo_helper.rb

なるほど、resourceからmodelを差し引いた感じのものが生成されるようです。 最初から入っているuserモデルのコントローラを生成するのに便利そうですね。

posted by Png genki on Thu 20 Nov 2008 at 13:06

PassengerはRackに対応しているので、Merbも動かすごとができます。

以下のように、Merbアプリケーションのディレクトリの直下に config.ruファイルを作成して置くだけです。

   1  require 'rubygems'
   2  require 'merb-core'
   3  Merb::Config.setup(:merb_root   => ".",
   4    :environment => ENV['RACK_ENV'])
   5  Merb.environment = Merb::Config[:environment]
   6  Merb.root = Merb::Config[:merb_root]
   7  Merb::BootLoader.run
   8  
   9  # Uncomment if your app is mounted at a suburi  
  10  #if prefix = ::Merb::Config[:path_prefix] 
  11  #  use Merb::Rack::PathPrefix, prefix 
  12  #end 
  13  
  14  run Merb::Rack::Application.new

ちなみに ru はRack Upの事だと思われます。

ハマった点として、 Merbアプリのひな形の"/"で表示される画面は、エラーページなので、 production環境のPassengerで動かすとエラーとして扱われてしまいます。 なので、動作確認する場合、 なにかしらコントローラを作ってから試す必要があります。

posted by Png genki on Thu 20 Nov 2008 at 12:14

いつのまにか今まで動いていたRailsアプリケーションが、以下のようなエラーを出すようになっていました。

This version of RMagick was created to run with ImageMagick 6.4.3 but ImageMagick 6.4.5 is in use

どうやら、port upgradeを行ったときにlibmagickのバージョンがあがり、 インストールされているRMagickとのバージョンの対応が崩れてしまったようです。

一度RMagickの最新バージョンをアンインストールし、 もう一度gemコマンドでインストールし直した所、解決しました。

posted by Png genki on Thu 20 Nov 2008 at 02:20

早速Merb-1.0.1にアップデートする必要がでてきたので、手順をメモしておきます。

  1. config/dependencies.rbの中で、
       1  merb_gems_version = "1.0.1"
       2  dm_gems_version   = "0.9.7"
    
  2. dm-core,dm-aggregates,dm-migrations,dm-timestamps,dm-types, dm-validations,do_sqlite3 を0.9.7にアップデート

ここまでで、とりあえず merb -iは起動するようになりました。

posted by Png genki on Wed 19 Nov 2008 at 10:08

今月16日のMerb newsで、数日後にリリースされると予定されていた Merb-1.0.1がリリースされたみたいです。

Merb news nov-16-2008

Merb 1.0.1

Merb 1.0.1 is in the work and should be released in the next few days. It’s just a maintenance release, so nothing new but we expect to ship with the new upcoming version of DataMapper, optimized generator (you will be able to use spaces in between arguments if you follow the unix standard) and some bug fixes.

インストール/アップデートはRubyGemsで行えます。

   1  % sudo gem install merb

posted by Png genki on Wed 19 Nov 2008 at 09:27

merb -iは、 Merb-1.0におけるscript/console的な対話型インターフェイスを提供するコマンドですが、 アダプターとしてThinを使っていると、エラーが発生してうまく使えないようです。

   1  % merb -i
   2    (snip)
   3   ~ Connecting to database...
   4   ~ Loaded slice 'MerbAuthSlicePassword' ...
   5   ~ Parent pid: 29906
   6   ~ Compiling routes...
   7   ~ Activating slice 'MerbAuthSlicePassword' ...
   8  merb : worker (port 4000) ~ Starting Thin at port 4000
   9  merb : worker (port 4000) ~ Using Thin adapter on host 0.0.0.0 and port 4000.
  10  merb : worker (port 4000) ~ Successfully bound to port 4000
  11  /opt/local/lib/ruby/gems/1.8/gems/eventmachine-0.12.2/lib/eventmachine.rb:531:in
  12   `start_tcp_server': no acceptor (RuntimeError)

mongrelとwebratをインストールし、adapterとしてMongrelを使うようにすると、merb -iでエラーが出なくなりました。

   1  % merb -i
   2    (snip)
   3   ~ Connecting to database...
   4   ~ Loaded slice 'MerbAuthSlicePassword' ...
   5   ~ Parent pid: 29931
   6   ~ Compiling routes...
   7   ~ Activating slice 'MerbAuthSlicePassword' ...
   8  irb: warn: can't alias context from irb_context.
   9  irb(main):001:0> 

Merbの名称はMongrel+ERBから来てるみたいだけど、 とりあえずはしばらくMongrelを使っておくのが無難かもですね。 少なくとも開発環境では。

posted by Png genki on Wed 19 Nov 2008 at 08:57
posted by Png genki on Wed 19 Nov 2008 at 08:13

MerbでWebサーバのプロセスをデーモンモードで立ち上げる場合、 以下のように行います。

   1  % merb -d

これによって、log/の下に、merb.4000.pidのようなPIDファイルが作成されます。

立ち上げたプロセスをKillする場合は、以下のようにポート番号を指定して-kオプションを使います。

   1  % merb -k 4000

あるいは、gracefulにkillしたい場合は、-kの代わりに-Kを使います。

   1  % merb -K 4000

ポート番号を指定せずに、allを指定する事もできます。

   1  % merb -K all

-kの方ではallは指定出来ないようです。

posted by Png genki on Tue 18 Nov 2008 at 03:49

Merbを使う時に、利用するWebサーバを切り替えるには、 以下のように、-aオプションを使う事ができます。

   1  % merb -a thin

毎回指定するのも面倒なので、config/environment/*.rb ファイルの中で、 以下のように設定する事もできます。

   1  Merb::Config.use { |c|
   2    # snip
   3    c[:adapter] = :thin
   4  }

posted by Png genki on Tue 18 Nov 2008 at 03:35