From: しん <dezawa / aliadne.net>
Subject: [ruby-list:46364] Re: メソッドの間接?実行
Date: Sun, 6 Sep 2009 19:59:56 +0900

>   返信を作って In-Reply-To  References を消すってよくやっているのですが、
>   今回消し忘れてしまいました。

返信を作らないで、メーリングリストのメールアドレスで新規メールを作成しましょう。

> この  def deletable?(roll) で case when をずるずる書かないでなんとか
> ならないものか、というのが質問です。

やや高度な技法ですが、Kernel#__send__で動的にメソッドを呼ばせる方法があります。
ついでに、よりRubyらしいコードに直しておきました。

class Document
  # true/falseはそのまま。シンボルは判定メソッド。
  Deletable={
    1 => [true  ,false ],
    2 => [:form1 ,false ],
    3 => [:form2 ,false ]
  }
  def initialize(form,status)
    @form   = form
    @status = status
  end
  
  def deletable?(roll)
    case result = Deletable[roll][@status]
    when true, false ; result           # true/falseならそのまま
    when Symbol      ; __send__(result) # シンボルで指定されたメソッドを動的に呼ぶ
    else             ; raise ArgumentError
    end
  end

  # 判定メソッド(メソッド名がよくないので意味のわかる名前に改名すべき)
  private                       # 内部用なのでprivateに
  def form1() @form == 1 end
  def form2() @form == 2 end
end


# ブロックパラメータの中で()が使える
# 数字よりもシンボルを使ったほうが可読性が上がる
[[1,0],[1,1],[2,0],[2,1]].each_with_index{|(form,status), idx|
   puts "form #{form} status #{status}"
   doc=Document.new(form,status)
   (1..3).each{|roll|           # 1〜3を表現したいなら範囲オブジェクトを使う
      print "  roll #{roll} ", doc.deletable?(roll),"\n"
   }
}
# >> form 1 status 0
# >>   roll 1 true
# >>   roll 2 true
# >>   roll 3 false
# >> form 1 status 1
# >>   roll 1 false
# >>   roll 2 false
# >>   roll 3 false
# >> form 2 status 0
# >>   roll 1 true
# >>   roll 2 false
# >>   roll 3 true
# >> form 2 status 1
# >>   roll 1 false
# >>   roll 2 false
# >>   roll 3 false

--
rubikitch
Blog: http://d.hatena.ne.jp/rubikitch/
Site: http://www.rubyist.net/~rubikitch/
Twit: http://twitter.com/rubikitch/
『Ruby逆引きハンドブック』 http://d.hatena.ne.jp/rubikitch/20090525/rubybook