【一人 bugs.ruby Advent Calendar 2021】[Feature #11689] Add methods allow us to get visibility from Method and UnboundMethod object.【17日目】
一人 bugs.ruby Advent Calendar 2021 17日目の記事になります。
今回はメソッドオブジェクトに対してアクセシビリティの情報を取得するメソッドの話です。
[Feature #11689] Add methods allow us to get visibility from Method and UnboundMethod object.
メソッドのアクセシビリティを返す Method#visibility
UnboundMethod#visibility
を追加する提案です。
Method#visibility
はアクセシビリティに応じて :public
:protected
:private
のいずれかが返ってくる想定です。
ユースケースとしては任意のメソッドをラップする場合に元のメソッドと合わせるために使用することができます。
具体的にはこういうケース や以下のケースなど。
class Object def debugging(name) original = instance_method(name) # 提案 # visibility が `:public` `:protected` `:private` を返す method_visibility = original.visibility # 既存の実装だとこう書く必要がある # method_visibility = if private_method_defined?(name) # :private # elsif protected_method_defined?(name) # :protected # else # :public # end define_method(name) { |*args, &block| pp name original.bind(self).call(*args, &block) } # 元のメソッドに合わせる send(method_visibility, name) end end class X def hoge pp 1 + 2 end private :hoge debugging :hoge end # error: private method `hoge' called for #<X:0x000055f0b1abf3e0> (NoMethodError) X.new.hoge
このチケットでは色々と議論が進んでいたんですが最終的には元々の提案の #visibility
は入りませんでした。
その代わりとして {Method,UnboundMethod}#{public?,private?,protected?}
のようにアクセシビリティを判定するメソッドが追加されました。
def hoge end pp method(:hoge).private? # => true pp method(:hoge).public? # => false public :hoge pp method(:hoge).private? # => false pp method(:hoge).public? # => true
最初に提示されたユースケースだとこんな感じで利用することができます。
class Object def debugging(name) original = instance_method(name) # 既存の実装だとこう書く必要がある method_visibility = if original.private? :private elsif original.protected? :protected else :public end define_method(name) { |*args, &block| pp name original.bind(self).call(*args, &block) } # 元のメソッドに合わせる send(method_visibility, name) end end class X def hoge pp 1 + 2 end private :hoge debugging :hoge end # error: private method `hoge' called for #<X:0x000055f0b1abf3e0> (NoMethodError) X.new.hoge
どちらかと判定メソッドが必要なケースが多そうなのでこっちのほうが汎用性は高そうですね。