こんにちは、プレイライフの熊﨑です!
rubyのsendメソッドがどんなことをしてくれるメソッドなのかはなんとなく理解していましたが、どんなメリットがあるかまでは恥ずかしながら理解しておりませんでした。
そこで、今回はsendメソッドのメリットについてまとめていきたいと思います!
sendメソッドとは?
レシーバーの持っているメソッドを文字列やシンボルで指定して呼び出すメソッド
以下のように書きます。
sample.rb
# Foo.barと書くのと同じ
Foo.send("bar")
どんなメリットがあるのか?
- 条件分岐を書かなくても、メソッドを使い分けることができる。
例: 赤信号の場合stop, 青信号の場合goと表示するプログラム
signal.rb
class TrafficSignal
# 今は2つしか条件がないが、この条件が膨らんでくると、コード量が増え、可読性も落ちてくる。
def display_message(signal_color)
if signal_color == "red"
display_red_message
elsif signal_color == "green"
display_green_messsage
end
end
def display_red_message
"stop"
end
def display_green_messsage
"go"
end
end
signal = TrafficSignal.new
puts signal.display_message("red")
puts signal.display_message("green")
sendメソッドを使用すると、以下のように書き換えることができる。
signal.rb
class TrafficSignal
# 条件分岐を書く必要がなくなる。
# def display_message(signal_color)
# if signal_color == "red"
# display_red_message
# elsif signal_color == "green"
# display_green_messsage
# end
attr_accessor :signal_color
def initialize(signal_color)
@signal_color = signal_color
end
def display_red_message
"stop"
end
def display_green_messsage
"go"
end
end
signal = TrafficSignal.new("red")
puts signal.send("display_#{signal.signal_color}_message")
注意点
ユーザーからの入力値をそのままsendメソッドに引き渡すと、悪意あるユーザーがrailsアプリを強制終了させることができてしまうので、要注意
sample.rb
# 下記のように書くと、悪意のあるユーザーがexitと入力した場合、アプリが終了する。
# exitはKernelモジュールに定義されているメソッド。KernelモジュールはBasicObject以外のすべてのクラスで使用可能。
signal.send("#{params[:signal_color]}")
まとめ
- sendメソッドはレシーバーの持っているメソッドを動的に呼び出すことができる。
- 便利な反面、使い方を誤るとセキュリティーホールを作ってしまうので注意して使用する必要がある。
参考文献
https://qiita.com/igrep/items/b2fed2d467f8a16f5eb0#fn1
https://docs.ruby-lang.org/ja/latest/method/Object/i/send.html