Search

検索したいワードを入力してください

2019年04月22日

Rubyのevalメソッドの基本から応用的な使い方までを解説

Rubyには、evalというメソッドが用意されており、このメソッドに引数として渡した文字列をそのまま実行させることが可能です。本記事では、Rubyのevalメソッドについて基本の使い方から応用に渡るまで、サンプルコードを交えながらご紹介します。

evalとは

Rubyで使われる「eval」は、「Rubyの実行コードを文字列として渡すメソッド」と理解すると良いでしょう。

【evalの使用例】
eval("puts 'Hello, world'")

evalの引数として指定する文字列は、ターミナルで直接puts "Hello, world”を実行するのと同じ結果となります。evalは実行する文のエラーチェックなどに使い、異常発生の検知に使うことができます。

evalの基本的な使い方を解説

Rubyのevalは、以下の基本構文で使用します。必須となる引数は、基本構文でexprと表記されている第1引数の実行コードのみです。

それ以外の引数は任意で指定します。第3引数と第4引数を指定する効果は、ファイル名fnameの行番号filenoに第1引数の実行コードが記述されているような振る舞いになります。

【evalの基本構文】
eval(expr [,bindingObj, fname, fileno])

evalの活用

Rubyのプログラミングの中で、複数の似たようなメソッドが存在するものの、メソッドの名称がそれぞれで異なる場合、以下のようなコード記述のようにそれぞれのメソッドを個別に記述することになります。

【コード記述例】
def Sample_a
puts "Sample_a"
end

def Sample_b
puts "Sample_b"
end

Sample_a # Sample_a の実行
Sample_b# Sample_bの実行

evalを活用したコードの書換え

この少し冗長的とも感じられるプログラムコードを、evalを使ってもっとすっきりと書き換えることができます。以下のように書き換えてみても、同じ内容で実行できることになります。

【コード書き換え例】
def sample(name)
eval("puts \"sample_#{name}\"")
end

sample("a") #Sample_aの実行
sample("b") #Sample_bの実行

bindSampleメソッドをBindingオブジェクトとして指定してみる

Rubyのevalメソッドの引数として第2引数に定義されているのは、bindingObjと表記されています。このbindingObjは、「Bindingオブジェクト」を示しています。

Bindingオブジェクトを使ったメソッドを定義したうえで、evalの第2引数として指定することができます。以下のサンプルコードを参照してみましょう。

サンプルコード
def bindSample
  sample_num= 100
  binding
end

eval("p sample_num", bindSample)

サンプルコードの解説

サンプルコードでは、「bindSample」というメソッドを定義し、ローカル変数sample_numに100を設定しています。

その後、bindingメソッドを実行し、Bindingオブジェクトを生成してbindSampleメソッドの戻り値として返します。

その結果、bindSampleメソッドの外部からbindSampleのローカル変数であるsample_numを参照することができるようになります。

Bindingオブジェクトを使わずローカル変数を引数に指定してみる

Bindingオブジェクトを使わず、evalを使って変数に値を設定し、evalで実行コードを指定する際の引数として指定してみましょう。

以下の実行コードでは、1つ目のevalで定義した変数は、ローカル変数の扱いとなり、2つ目のevalで実行しようとしているコードからは参照することができません。そのため、実行結果はエラーになります。

実行コードと実行結果
【実行コード】
eval("sample_num = 'this is sample code'")
eval("p sample_num")

【実行結果】
# undefined local variable or method `sample_num'

Bindingオブジェクトを使わずに変数をevalの引数に使用する

Rubyのevalメソッドを実行する前に定義されている変数であれば、Bindingオブジェクトでなくてもevalから呼び出したり、値を代入したりすることが可能です。

【実行コード】
sampleNum= "a12a"
eval("p sampleNum")
eval("sampleNum= 'b34b'")
eval("p sampleNum")


【実行結果】
"a12a"
"b34b"

evalの応用的な使い方

Rubyのevalメソッドに関してリファレンスを参照すると、evalのほか3つの関連メソッドが用意されていることがわかります。Rubyで使用できるevalメソッドには、全部で4つのメソッドがあることになります。

・eval
・class_eval
・module_eval
・instance_eval

evalの応用的なメソッドとして、ほかの3種類のメソッドについても、使い方をご紹介します。

instance_evalメソッドの使い方

Rubyのinstance_evalメソッドは、渡されたブロックを実行します。サンプルコードを参照してみましょう。サンプルコードでは、Sample01クラスの中で定義した内部変数nameを、instance_evalに渡すブロック内で参照することができます。

サンプルコードと実行結果
【サンプルコード】
class Sample01
    def initialize
     @name = "instanceSample"
   end
end
x = Sam01ple.new
p x.instance_eval { @name }
【実行結果】
"instanceSample"

class_evalメソッドの使い方

Rubyのclass_evalメソッドでは、ブロックをクラス定義やモジュール定義の中のコードであるかのように実行します。ブロックの戻り値がclass_evalメソッドの戻り値となります。

サンプルコードでは、abcメソッドはSample02クラスのメソッドとしては定義していませんが、class_evalのブロック引数として指定すれば、Sample02クラス中のメソッドであるかのように実行できます。

サンプルコードと実行結果
【サンプルコード】
class Sample02; end
Sample02.class_eval { def abc; "This is abc method"; end }

puts Sample02.new.abc
【実行結果】
"This is abc method"

module_evalメソッドの使い方

Rubyのmodule_evalメソッドは、class_evalと同等の機能を持つメソッドです。使い方は、class_evalと同様で、class_evalのサンプルコードを、module_evalメソッドに置き換えてもそのまま動作させることができます。ブロックの戻り値がmodule_evalメソッドの戻り値となります。

サンプルコードと実行結果
【サンプルコード】
class Sample03; end
Sample03.module_eval { def hello; "This is abc method"; end }

puts Sample03.new.abc
【実行結果】
"This is abc method"

Rubyのevalメソッドを活用してみよう!

Rubyのevalメソッドの使い方について、理解できたでしょうか。どのような場面で、evalメソッドを活用できるか、イメージできたでしょうか。

まずはevalの基本的な使い方を、自分の開発コードの中で活用できるようになりましょう。evalの用途をきちんと把握できたら、引数を指定したり、応用編のnstance_eval、class_eval、module_evalについても積極的に使ってみましょう。

Related