method_missingに触れた~メタプログラミング~

はじめに

メタプログラミングは、プログラムが自身を操作したり変更したりすることを指します。 この辺りは知識としてあったんですが、実装で触れる機会も特にありませんでした。 業務でmethod_missingを使用する場面があって、「おお!これがメタプログラミングか!!」となったので、忘れないように書いていきます。

メタプログラミングとは

メタプログラミングは、プログラムが自身の振る舞いや構造を操作するプロセスらしい。

method_missing メソッドとは

method_missingは、Rubyの特別なメソッドの一つです。 method_missingを見た時に、「魔法やん!」って思っていたら色々な記事で魔法と言っていたので、認識は正しかったようです。 これを初見で見た時に理解できないことは私は魔法学校出身ではないことの証明でもあるので実装で詰まっていた時間も許せるなと思いました。

method_missingはどんなメソッドかというと、オブジェクトが存在しないメソッドが呼び出された際に自動的に呼び出されます。 これを活用することで、未定義のメソッドに対する柔軟な処理が可能になります。 No method errorがない世界ですね

method_missing の使用法

  • 基本的な構文
def method_missing(method_name, *args, &block)
  # 未定義のメソッドが呼ばれた際の処理を記述する
end
  • method_nameは呼び出されたメソッドの名前を表し、argsは引数の配列、blockはブロックを表します。

  • respond_to_missing?メソッドの実装

  • method_missingを使う際には、対応するrespond_to_missing?メソッドも実装することが推奨されます。 これは、オブジェクトが特定のメソッドを実装しているかどうかを判断するために用いられます。
def respond_to_missing?(method_name, include_private = false)
  # method_name が対応するメソッドを実装しているかを返す処理を記述する
end

method_missing の活用例 動的な属性アクセス method_missing を使用する典型的な例は、動的な属性アクセスの実装です。以下のようなクラスを考えてみましょう。

class DynamicAttributes
  def initialize
    @attributes = {}
  end

  def method_missing(name, *args)
    if name.to_s =~ /^set_(.*)=$/
      @attributes[$1] = args[0]
    elsif @attributes.key?(name.to_s)
      @attributes[name.to_s]
    else
      super
    end
  end

  def respond_to_missing?(name, include_private = false)
    name.to_s.start_with?('set_') || @attributes.key?(name.to_s) || super
  end
end

このクラスでは、set_で始まるメソッドが呼ばれた際に、それに対応する属性を動的に設定します。また、属性の値を取得するためのメソッドも同様に動的に生成されます。

dynamic_obj = DynamicAttributes.new
dynamic_obj.set_name = "John"
dynamic_obj.set_age = 30
puts dynamic_obj.name  # => "John"
puts dynamic_obj.age   # => 30

まとめ

method_missingは、Rubyにおける強力なメタプログラミング機能の一つです。 その適切な活用により、柔軟性の高いコードを実現することができます。しかし、過度な使用はコードの可読性や保守性を損なう恐れがあるため、慎重に使う必要があります。是非、実際の開発でmethod_missingを活用し、Rubyメタプログラミングの世界を探索してみてください。