rubyのクラス同士の継承関係を比較する演算子についてのメモ。

   1  >> class Foo;end
   2  >> class Bar<Foo;end
   3  >> class Baz<Foo;end
   4  >> [Foo < Bar, Bar < Foo, Foo > Bar, Bar > Foo]
   5  => [false, true, true, false]
   6  >> Foo <=> Bar
   7  => 1
   8  >> Foo <=> String
   9  => nil
  10  >> Bar <=> Foo
  11  => -1
  12  >> Bar <=> Baz
  13  => nil

また、以下のようにモジュールのinclude関係も取得出来ます。

   1  >> module Goo;end
   2  >> class Foo;include Goo end
   3  >> Foo < Goo
   4  => true
   5  >> Foo > Goo
   6  => false
   7  >> Goo < Foo
   8  => false
   9  >> Goo > Foo
  10  => true

posted by Png genki on Sun 25 Jan 2009 at 20:47

Rubyで、クラスの内部から基底クラスのメソッドを呼び出す場合は、 superを使えば良いのですが、 どうしても外部から基底クラスのメソッドを呼び出したい場合には、 以下のようにすれば実現出来ます。

   1  >> class Foo; def foo; puts "foo#{self}"; end end
   2  => nil
   3  >> class Bar < Foo; def foo; puts "bar#{self}"; end end
   4  => nil
   5  >> Bar.new.foo
   6  bar#<Bar:0x25c2d60>

このように、通常は基底クラスのメソッドを直接呼び出す事は出来ませんが、

   1  >> Foo.instance_method(:foo).bind(Bar.new).call
   2  foo#<Bar:0x25b7f00>

一度UnboundMethodにしてから、もう一度バインドする事で、 基底クラスのメソッドを呼び出す事が出来ます。

posted by Png genki on Sun 25 Jan 2009 at 06:43

Merbを使ってWebアプリケーションを開発している or しようと考えている方の為に、 お勧めのプラグイン/Slice情報を共有するサービス Merbist Plugins をテスト公開いたします。

ss

デザインもScaffoldに毛が生えた程度で、 この手のサービスには欠かせないRatingなどの基本機能が無い状態なのですが、 そもそもMerbのプラグイン情報を共有する場所が無いので、 無いよりはちょっとましかなという事で公開しておきます。

merb_rating, dm-has-rating のようなプラグインを見つけたら、 あるいは作ったら、Rating出来るようになると思います。

ちなみに、新着プラグインのFeedも配信しています。

よろしくお願いします。

posted by Png genki on Sat 24 Jan 2009 at 02:50

本日(2009年1月23日)の10:20〜10:40の間、 弊社が提供しているウェブサービスに接続しにくくなるトラブルが発生いたしました。

原因としては、利用している外部サービスが一時的に停止した事を検出する処理に問題があり、連鎖的に影響を受けてしまった可能性が高いと思われます。 現在は当該箇所を修正の上、復旧いたしております。

ご不便をおかけいたしました事をお詫びいたします。

posted by Png genki on Fri 23 Jan 2009 at 11:02

githubの仕様変更 により、githubでEdgeGem (EdgeのコードをGemにまとめたもの) を常にフレッシュな状態で公開する事が難しくなってしまったので、 Merbist向けにプラグイン配布用のGemサーバを用意しました。

gems.rubyforge.orgやgems.github.comなどの通常のGemサーバと同様に、以下のようにsourcesに登録して使う事ができます。

   1  % sudo gem sources -a http://merbi.st

仕組みとしては、http://merbi.st/fetch にアクセスされると、 登録されているgithub上のリポジトリから、Edgeのコードがpullされ、 GemとGemサーバ用のインデックスデータを作成します。

現時点では、以下のGemを公開しています。

   1  % gem list -r -s http://merbi.st
   2  
   3  *** REMOTE GEMS ***
   4  
   5  dm-has-versions (0.1.1)
   6  dm-pagination (0.1.1)
   7  merb_babel (0.1.2.2)
   8  merb_component (0.1.1)
   9  merb_recognize_path (0.0.2)
  10  merb_slice-gen (0.0.2)
  11  merb_timezone_select (0.0.2)
  12  pagination_scope (0.0.8)
  13  rttool (1.0.2)

サーバの負荷の面で不安があるので、 現時点では同期するリポジトリの登録は管理者のみに制限していますが、 http://merbi.st/plugins よりプラグイン情報を登録していただければ(要アカウント作成)、 問題が無い限り定期的に確認して同期リストに追加いたします。

反応がない場合は@takiuchi までご一報ください。

posted by Png genki on Fri 23 Jan 2009 at 05:16

最近書いたNested Resourceに関する話題をまとめておきます。

外部サイトからのリンクバックもまとめ記事作成のための検索対象に含めたら、もっと便利になるかな。

posted by Png genki on Fri 23 Jan 2009 at 04:55

config/dependency.rbの形式が変わったようなので、メモです。

   1  # dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.
   2  merb_gems_version = "1.0.8.1"
   3  dm_gems_version   = "0.9.9"
   4  do_gems_version   = "0.9.10.1"
   5  
   6  # For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components
   7  dependency "merb-core", merb_gems_version
   8  dependency "merb-action-args", merb_gems_version
   9  dependency "merb-assets", merb_gems_version
  10  dependency("merb-cache", merb_gems_version) do
  11    Merb::Cache.setup do
  12      register(Merb::Cache::FileStore)
  13    end
  14  end
  15  dependency "merb-helpers", merb_gems_version
  16  dependency "merb-mailer", merb_gems_version
  17  dependency "merb-slices", merb_gems_version
  18  dependency "merb-auth-core", merb_gems_version
  19  dependency "merb-auth-more", merb_gems_version
  20  dependency "merb-auth-slice-password", merb_gems_version
  21  dependency "merb-param-protection", merb_gems_version
  22  dependency "merb-exceptions", merb_gems_version
  23  
  24  dependency "data_objects", do_gems_version
  25  dependency "do_sqlite3", do_gems_version # If using another database, replace this
  26  dependency "dm-core", dm_gems_version
  27  dependency "dm-aggregates", dm_gems_version
  28  dependency "dm-migrations", dm_gems_version
  29  dependency "dm-timestamps", dm_gems_version
  30  dependency "dm-types", dm_gems_version
  31  dependency "dm-validations", dm_gems_version
  32  dependency "dm-serializer", dm_gems_version
  33  
  34  dependency "merb_datamapper", merb_gems_version

merb_gems_version、 dm_gems_version、 do_gems_version の三つの系列のバージョンに分かれたのですね。

posted by Png genki on Thu 22 Jan 2009 at 19:13

Merbのspecで、Merb::Test::ViewHelperを使う場合には、 webratをインストールする必要があります。 merb-core/test/matchers.rbの中で、こんな感じの条件が書かれています。

   1  if defined?(::Webrat)
   2    module Merb::Test::ViewHelper
   3      include ::Webrat::Matchers
   4      include ::Webrat::HaveTagMatcher
   5    end
   6  end

posted by Png genki on Thu 22 Jan 2009 at 06:42

サーバのメモリ使用量が増えてきたので、30%のメモリ使用量削減を謳っているRuby Enterprise Editionを試してみる事にしました。 しかし、onigurumaの拡張ライブラリのインストールで若干手間取ったので、 解決方法をメモしておきます。

   1  # /opt/ruby-enterprise-1.8.6-20090113/bin/gem install oniguruma -- --with-opt-dir=/opt/local

こんな感じでインストールすると良いようです。

posted by Png genki on Thu 22 Jan 2009 at 04:29

まずはネストという言葉に関する定義の問題ですが、 諸橋さんが書いているように 、PostsコントローラはComments コントローラを集約(aggregates)しますが、 内包(compose)する訳ではありません。

たとえば、管理画面に対応するAdminコントローラから、 Commentの削除や修正を行う場合に、AdminコントローラからCommentsコントローラを集約する事を考えると、その必要性が分かりやすいと思います。

PostsコントローラにCommentsを制御するコードを書いてしまう(内包してしまう)と、 Adminコントローラで同じ事をする必要が出来た場合に、 同じようなコードを書く必要が出てきます。

Don't Repeat Yourself!

結果として、メンテナンス性の悪いコードが出来上がります。 この事が、Postsコントローラの中でCommentsリソースを制御する コードを書く事の問題の本質だと思います。 もちろん、あらかじめCommentsを集約する存在が Postsしか無いと分かっている場合には問題ありません。

という事で、 続いて検索やCRUD以外の操作はどうするのかという問題について。

この問題を考えるための重要な視点として、最近のRailsやMerbでは、 リソースを制御するためのリソースコントローラと、 それ以外の制御をするための汎用コントローラの役割が分けて考えられるようになってきているという事があります。

上述の話の中で登場するコントローラを当てはめてみると、 以下のようになります。

コントローラの分類
リソースコントローラ汎用コントローラ
PostsAdmin
CommentsDashboard

リソースコントローラとは、特定のモデルに対してCRUD(create, read, update, delete)操作を行う事に特化したコントローラです。

そう考えると、検索やCRUD以外の操作は、 汎用コントローラが行うのが自然な気がします。 例えば、ブログの記事(Posts)やコメント(Comments) の検索を行う場合であれば、 SearchコントローラがPostsコントローラやCommentsコントローラ を集約すればOK. 疑似コード的に表現すると、以下のような感じになります。

   1  Search#posts with_scope(query){ Posts#index }
   2  Search#comments with_scope(query){ Comments#index }

この構造は2年ぐらい前にRailsで使ってみたのですが、 Railsのコントローラの実装がネストに向いていないので、 パフォーマンス上の問題に苦しみました。 Railsのコントローラは、フィルタの実行、アクションの実行だけでなく、レスポンスの作成を担っているので、ネストさせた場合に、 いったん作成したレスポンスを破棄する必要があるなど、無駄が大きいのです(Railsではお馴染みのDoubleRenderErrorが発生するのもこのせいです)

しかし今であれば、Merbを使う事によってこの問題は解決します。 Merbのコントローラはレスポンスの作成をする必要が無く、非常にシンプルなので、ネストさせてもパフォーマンスの問題はほとんどありません。

ということで、Merbを使えばみんなHappyになるよという話でした。

前回の記事の追補

前回の記事では、Aggregatorの#showで、POST, PUT, DELETEを Aggregatedに委譲するという話を書きましたが、 例えばPostsコントローラがCommentsとTrackbacksの 2つのリソースを集約している場合に、 どちらのリソースに対する操作なのかを判別する方法を用意する必要があるので、どうやって実現するか書いておきます。

   1  posts/1            -> Posts#show
   2  posts/1/comments   -> Posts#show -> Comments
   3  posts/1/trackbacks -> Posts#show -> Trackbacks

こんな感じに、posts/1/:resource に対するPOST, PUT, DELETEを、 :resourceに対応するリソースコントローラに委譲する感じですね。

posted by Png genki on Wed 21 Jan 2009 at 10:19