🗂

[Feature #20428] メソッドが呼び出されたときにそれが定義されているクラスを取得したい

2024/04/16に公開

[Feature #20428] Ability to reference current class/module in lexical scope

  • 以下のように『モジュールのメソッドが呼ばれたときに『呼び出されたクラス/モジュール』ではなくて『定義したスコープのクラス/モジュール』を取得したい』という要望
module Foo
  module Bar
    def blah
      # このときに『現在のスコープのクラス』を取得したい
      # Foo::Bar を取得することを期待する
      puts "executing from #{magic_new_keyword}"
    end
  end
end

class Baz
  include Foo::Bar

  def blah
    super

    puts "executing from #{self.class.name}"
  end
end

Baz.new.blah
# 以下のような結果を期待する
# executing from Foo::Bar
# executing from Baz
  • 単純に self.class.name で取得すると『呼び出されたレシーバのクラス』が返ってくるので Baz が返ってくるんですが Foo::Bar を取得したい意図ですね
  • このケースでは Module.nesting.first が利用できるとコメントされています
module Foo
  module Bar
    def blah
      puts "executing from #{Module.nesting.first}"
    end
  end
end

class Baz
  include Foo::Bar

  def blah
    super

    puts "executing from #{self.class.name}"
  end
end

Baz.new.blah
# output:
# executing from Foo::Bar
# executing from Baz
  • Module.nesting はこのメソッド呼び出した個所に依存するような『クラス/モジュールのネスト情報』を配列で返します
module Foo
  module Bar
    pp Module.nesting   # => [Foo::Bar, Foo]
    class Hoge
      def blah
        pp Module.nesting
        # => [Foo::Bar::Hoge, Foo::Bar, Foo]
      end
    end
  end
end

Foo::Bar::Hoge.new.blah
  • これで解決できたみたいなのでチケット自体は閉じられてます
GitHubで編集を提案

Discussion