rubyのevalメソッドとは

2022.06.26

evalメソッドとは

文字列 expr を Ruby プログラムとして評価してその結果を返します

Ruby 3.0.1 リファレンスマニュアル

第1引数に渡された文字列をrubyプログラムとして実行する。第1引数は必須。

eval(expr, bind, fname = “(eval)”, lineno = 1) -> object

  • expr・・評価する文字列
  • bind・・評価するコンテキスト(スコープを付与する時に使う)
  • fname・・スタックトレースに表示するファイル名
  • lineno・・exprが書かれていると想定した時の行番号の整数

どう省略されるか

evalを使わない場合

def a 
 p "hello" 
end
a #=> "hello"

evalを使った場合

eval('def a; p "hello" end')
a #=> "hello"

第3、第4引数

第3、第4引数使ってeval.rbファイルの4行目でエラーが起きたことにできる

eval('raise RuntimeError', binding, 'eval.rb', 4)
#=> eval.rb:4:in `<main>': RuntimeError (RuntimeError)
#=> from eval.rb:4:in `eval'
#=> from eval.rb:4:in `<main>'

bindingの使い方

変数やメソッドのスコープを付与する時に使う。

bindingの記載位置は意識したほうがよさそう。

  • メソッドの最後に記載する
  • 複数記載しても実行されるのは最後のみ
# aメソッドのhiのスコープを使えるようになる(スコープが付与された)
def a
 hi = "こんにちは"
 binding
end
eval('p hi', a)
#=> "こんにちは"


# bメソッドにはhiはないのでエラーになる(スコープがずれてる)
def b
 bye = "バイバイ"
 binding
end
eval('p hi', b)
#=> `b': undefined local variable or method `hi' for main:Object (NameError)

まとめ

evalを使うことで文字列をrubyプログラムとして扱えるようになる。またbindingを使うことでスコープを付与することができる。

rubyプログラムを文字列で渡したい場合に使える。メソッド化したくない処理とか?

※追記

evalメソッドは極力使わない方が良い。脆弱性が高まる。effective rubyにも『これは非常に危険なことだ』と書かれてた。