LoginSignup
38
23

More than 3 years have passed since last update.

Rubyのsendメソッドを使用するメリットと注意点

Last updated at Posted at 2019-06-16

Qiita初投稿です。よろしくお願いします。

はじめに

Rubyのsendメソッドを仕事中に使用する機会があり、便利!と思ったものの、慎重に使う必要があることがわかったのでまとめました。

参考文献

現場で使える Ruby on Rails 5速習実践ガイド

sendメソッドとは

レシーバーが持っているメソッドを、文字列(またはシンボル)で指定して呼び出します。
つまり、メソッドを動的に呼び出すことができます。

どんなときに使えるか

以下のように、caseの値によって呼び出すメソッドが異なる場合、caseが増えれば増えるほどコードが膨らんでいき、可読性が下がります。

# 値によって実行するメソッドを分岐させる
class Shape
  def create_shape(shape_type)
    case shape_type
    when "circle" then
      create_shape_circle
    when "square" then
      create_shape_square
    when "triangle" then
      create_shape_triangle
    end
  end

  def create_shape_circle
    ...
  end

  def create_shape_square
    ...
  end

  def create_shape_triangle
    ...
  end
end

shape = Shape.new
shape.create_shape("circle")

上記のコードをsendメソッドを使って書き直すとこうなります。


class Shape
  attr_accessor :shape_type

  def initialize(shape_type)
    @shape_type = shape_type
  end

  def create_shape_circle
    ...
  end

  def create_shape_square
    ...
  end

  def create_shape_triangle
    ...
  end
end

shape = Shape.new("circle")
shape.send("create_shape_#{shape.shape_type}")

メソッドを動的に呼び出せるため、caseでの分岐が不要になりました!
ただし、sendに渡す値によっては、sendを使用せずにメソッドを固定的にコーディングした方が良い場合があります。

sendメソッドに渡してはいけない値

sendメソッドは動的にプログラムの動作を変えられる反面、使い方を誤ると深刻なセキュリティ問題を引き起こす恐れがあります。

特に、ユーザーからの入力をそのままsendに引き渡すと、意図せぬ範囲のデータやプライベートメソッドにまで影響が及ぶ可能性があります。

例)悪意のあるユーザーが「exit」と入力した場合、それがsendに渡されるとアプリケーションが終了してしまう。
※exitはKernelモジュールに定義されているメソッド。KernelモジュールはBasicObject以外のすべてのクラスで使用可能。

そのため、外部から入力された値によって呼び出すメソッドを分岐させる場合は、最初のcase文の例のように、ユーザーの入力を切り分けて個々のメソッドの呼び出しを固定的にコーディングした方が安全です。

まとめ

sendメソッドは動的なメソッド呼び出しができて便利だが、セキュリティ面を考慮し、外部の入力に依存する値は渡さないようにする。

38
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
23