dRubyでmethod_missing

メソッドの可視性の実現方法を修正して、method_missingを使うオブジェクトを リモートから利用できるようにしました。

メソッドの可視性

というか呼び出し制限について、dRubyではpublicなメソッドのみを呼び出せるようにしています。 従来は、respond_to?を用いて検査していたのですが、privateでもprotectedでもない、という 検査に変更しました。

この変更により定義されていないpublicなメソッド(一般にmethod_missingを使ったトリックで実現される)を 呼び出すことができるようになります。

method_missingの例

mm.rb / server

未知のメッセージを受け取ると、それを文字列にして返すサーバです。 役には立ちませんが実験には十分です。

require 'drb/drb'

class Foo
  def method_missing(msg, *arg, &block)
    'method_missing: ' + msg.to_s
  end
end

DRb.start_service(nil, Foo.new)
puts DRb.uri
DRb.thread.join

mmc.rb / client

mm.rbを呼び出すスクリプトです。 hello_world, druby_book_2などのメソッドを呼び出します。 またprivate methodであるevalを呼び出してエラーになることを確認します。

require 'drb/drb'

uri = ARGV.shift

DRb.start_service
mm = DRbObject.new_with_uri(uri)
p mm.hello_world
p mm.druby_book_2
begin
  p mm.eval('error')
rescue
  p $!
end

実験

まあ、こんなのです。

[ターミナル1]
% ruby mm.rb 
druby://four.local:51758

[ターミナル2]
% ruby mmc.rb druby://four.local:51758
"method_missing: hello_world"
"method_missing: druby_book_2"
#<NoMethodError: private method `eval' called for #<Foo:0x353c3c>:Foo>

Link

RedHandedにて、Coolなmethod_missingに関する議論がなされています。