nekoTheShadow’s diary

技術ブログとして始めたはずが、読書&愚痴ブログになりました(´・ω・`)

Paolo Perrotta 『メタプログラミングRuby』を読んだ……といえるのかしら。

メタプログラミングRuby

メタプログラミングRuby

 Rubyプログラマの中で非常に評価が高い『メタプログラミングRuby』。前々から気になっていたものの、残念ながら絶版。しかも中古も安くて5000円程度するということで、あきらめかけていたところ――偶然にも大学図書館で発見! うちの大学、文系の単科大学なんですが……。

 ただ見つけたといっても、本そのものは禁貸出。そのうえ悪いことに見つけたときのわたしには1時間弱しか時間がなかったため、とるものもとりあえず目を通すことに。つまり「読んだ」といっても、たとえば「掲載コードを写経した」とか「詳細にノートを作った」とかではなく「ページをめくって文章を理解した」だけ。    これを果たして「読んだ」といえるのか。疑問は残るところですが、とりあえず読書メモは残しているので、気になったところ・面白かったところをブログに書いておきます。

define_method

 define_methoddefを利用せず、メソッドを定義することができるメソッド。そのため次のようなことができます。

str = "hello world"

def hoge1
  p str
end

define_method(:hoge2) do
  p str
end

hoge1 #=> strが定義されていないためerror
hoge2 #=> "hello world"

method_missing

 本来そのクラスやモジュールにないメソッドを呼び出した場合、NoMethodErrorが発生しますが、このmethod_missingをインクルードしていた場合、こちらが代わって呼び出されます。

class Hoge

  def method_missing(method)
    p "#{method}なるメソッドはこのクラスに存在しません!"
  end

end

hoge = Hoge.new
hoge.hello #=> "helloなるメソッドはこのクラスに存在しません!"

   このmethod_missingのように、「何らかの処理が行われたとき、その変化を検出したり、割り込んで別の処理を行ったりする」ことをフックといい、それを実現するメソッドフックメソッドというそう。本書ではほかにもRubyのフックメソッドが紹介されていました(ex.クラスにモジュールがインクルードされたことを検出するメソッド)が、とりわけmethod_missingインパクトが強かった。

send

 sendは引数のメソッドを実行するメソッドです。意義としてSymbolやStringをメソッドとして実行できることにあります。「メソッド名に正規表現を適用して実行」なんてこともできるわけですね(例は思いつきませんが)。

def hoge
  p "hello world"
end

sym = :hoge
send(:hoge) #=> "hello world"

 またsendはレシーバをとることもでき、その場合引数はそのレシーバのインスタンスメソッド・クラスメソッドとして実行することが可能です。

class Hoge

  def hello
    p "hello world"
  end

end

hoge = Hoge.new
hoge.send(:hello) #=> "hello world"

eval

 evalは引数をRubyのコードとして実行するメソッドです。

str = "p hello world"
eval(str) #=> "hello world"

 またevalには「親戚」が多く、レシーバにクラスをとって引数をクラス内の一部とみなすclass_evalや、インスタンスをレシーバにとるinstance_evalなどがあります。

class Hoge
    
  def initialize(str)
      @str = str
  end
    
end

Hoge.class_eval{
  def say
      p @str
  end
}

hoge = Hoge.new("hello")
hoge.say #=> "hello"
hoge.instance_eval{p @str} #=> "hello"

alias

 aiasメソッドに別名をつけるメソッドです。いろいろ細かい使い方があるようですが、それを全くメモしていない……。反省。

class Hoge
    
    def hello
        p "hello"
    end
    
    alias :say :hello
    
end

hoge = Hoge.new
hoge.say #=> "hello"

$SAFE

 $SAFEはセキュリティレベルを設定するグローバル変数です。初期値は0で、最大値は4。数字が大きくなるほど、セキュリティレベルが上がり、4にもなるとセキュリティ上危険なことは全くできなくなります。これだけ具体例が思いつかなかったのは内緒。

まとめ

 なんだかとりとめのない読書メモになってしまいましたね。あわてて読んだためにメモが不完全で、この体たらく。時間がなかったとはいえ、これは反省。

 ここでは目立ったものを紹介しただけですが、本ではこれら「黒魔術」メソッドをどのように組み合わせるのか、あるいはどのように実践へ結び付けていくのか、わかりやすく解説されています。とりわけ最後のほうにある「ActiveRecordの解説」は圧巻でした。

 手に入る機会があれば、手元においておきたい本です。絶版だけど。今度時間があるときは図書館にこもって、写経しながら中身を血肉に変えていきたいと思います。