Object#public_send()で安全にメソッドを呼び出す

rubyで動的にメソッド呼び出しをしたい時、Object#send()を使うと文字列やシンボルでメソッドを呼び出す事が出来ます。
ただこの機能を使うと意図せずにカプセル化を壊す事が出来てしまうため、publicメソッドのみ呼び出すようにしたい場合はObject#public_send()を使うと良いです。

myclass.rb

class MyClass
  def hoge
    "hogehoge"
  end
  
  private
    def fuga
      "fugafuga"
    end
end

public_sendを使ってprivateメソッド(fuga)を実行してみます。

[2] pry(main)> require './myclass.rb'
=> true
[3] pry(main)> obj = MyClass.new
=> #<MyClass:0x007fe89b2043e8>
[4] pry(main)> obj.send(:hoge)
=> "hogehoge"
[5] pry(main)> obj.send(:fuga)
=> "fugafuga"
[6] pry(main)> obj.public_send(:hoge)
=> "hogehoge"
[7] pry(main)> obj.public_send(:fuga)
NoMethodError: private method `fuga' called for #<MyClass:0x007fe89b2043e8>
from (pry):7:in `public_send'

NoMethodErrorが発生しました。

少人数や小規模で開発する時はあまり気にしなくてもよさそうですが、一定以上の規模の開発やメンバーにプログラミング初心者が含まれている場合は、共通で使うライブラリなどでObject#send()の代わりに使っておけば事故が減りそうです。

http://ruby-doc.org/core-1.9.3/Object.html#method-i-public_send


参考書籍

メタプログラミングRuby

メタプログラミングRuby