【初心者必見!】Ruby evalを理解し活用するための4つのTips

こんにちは! フリーエンジニアの長瀬です。

みなさんはevalを使っていますか?

evalを使えば、evalに渡した文字をRubyプログラムとして実行させることができます。

この記事では、rubyのevalについて

・evalの使い方
・Bidingオブジェクトの指定

という基本的な内容から、

・instance_evalの使い方
・class_evalの使い方
・module_evalの使い方

といった応用的な内容についても解説していきます。

evalとは

evalとは何かを一言で説明すると「引数として与えた文字列をRubyプログラムとして実行するメソッド」です。

引数として与えた文字列を評価することができ、実行する文のエラーチェックに使うことができるので、異常発生を検知するときに使えます。

基本的なevalの使い方

evalの使い方

evalの基本的な使い方としては下記のように評価する式を引数として与えるだけです。

eval("puts 'Hello, everyone !'")

正式な構文は以下のようになっています。

eval(expr [,bindingObj, fname, fileno])

指定が必須なのは第1引数のみです。それ以外の引数指定は任意です。

第3引数fname, 第4引数filenoが与えられた場合、ファイル名fnameの行番号filenoに評価する式exprが書かれているかのように見せることができます。第2引数に指定するBindingオブジェクトは次の章で説明します。

例えば、スタックトレースに表示されるファイル名やソースファイルの行番号を自由に変更できます。

下記はサンプルコードです。sample.rbの10行目に「raise RuntimeError」が書かれているかのように見せることができます

eval('raise RuntimeError', binding, 'sample.rb', 10)
# sample.rb:10: RuntimeError (RuntimeError)

Bindingオブジェクトの指定

evalメソッドの第2引数には「Bindingオブジェクト」を指定することができます。

変数やメソッドにはそれらが有効な範囲(スコープ)があります。その定義されたスコープを表すオブジェクトがBindingオブジェクトです。

例えば、あるメソッド内で定義された変数をそのメソッドの外部から使用したいときに指定します。

下記のサンプルコードを使いながら、Bindingオブジェクトについて説明します。

def bindSample
hoge = 100
binding # Bindingオブジェクトの生成
end

eval("p hoge", bindSample)

[実行結果]

100

bindSampleメソッド内において、ローカル変数hogeを定義しています。

またbindingメソッドを実行することにより、bindSampleメソッドのBindingオブジェクトを生成して返します。

だからこそ、bindSampleメソッドの外部からローカル変数hogeを参照することができるわけです。

なので、たとえば以下のように、eval内でローカル変数を定義した場合evalで参照することができず、エラーを返します。

eval("hogehoge = 'this is hoge'")
eval("p hogehoge")

[実行結果]

# undefined local variable or method `hoge'

ですが、すでに定義されている変数についてはevalから呼び出したり値を代入したりできます。

hogehoge = "this is hogehoge."
eval("p hogehoge")
eval("hogehoge = 'changed'")
eval("p hogehoge")

[実行結果]

"this is hogehoge."
"changed"

eval応用編

instance_evalの使い方

instance_evalメソッドは、渡されたブロックを実行するものです。以下がサンプルコードです。

class InstanceEvalSample
def initialize
@name = "hoge"
end
end

x = InstanceEvalSample.new
p x.instance_eval { @name }

[実行結果]

"hoge"

このように、インスタンス変数nameをブロック内から参照する事ができます

class_evalの使い方

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

class ClassEvalSample; end
ClassEvalSample.class_eval { def hello; "Hello, everyone !"; end }

puts ClassEvalSample.new.hello

[実行結果]

 "Hello, everyone !"

helloメソッドは、ClassEvalSampleクラスの中で定義していないにも関わらず、その中で定義しているかのように実行できます

module_evalの使い方

module_evalはclass_evalのエイリアス(名前は違うけど、機能は同じ)です。

なので、class_evalで紹介したサンプルコードをそのままmodule_evalに置き換えることができます。

class ClassEvalSample; end
ClassEvalSample.module_eval { def hello; "Hello, everyone !"; end }

puts ClassEvalSample.new.hello

[実行結果]

 "Hello, everyone !"

まとめ

今回はevalの基本とその使い方について説明したのに加え、Bindingオブジェクトを指定する場合の使い方についても説明しました。

また、応用例としてinstance_evalclass_evalメソッド、module_evalについても紹介しました。evalと類似したメソッドでもありますので、evalの基本を理解した上で、上手く活用していきましょう!

「プログラミング、右も左もわからない…」という方にオススメ

当プログラミングスクール「侍エンジニア塾」では、これまで6000人以上のエンジニアを輩出してきました。

その経験を通してプログラミング学習に成功する人は、「目的目標が明確でそれに合わせた学習プランがあること」「常に相談できる人がそばにいること」「自己解決能力が身につくこと」この3つが根付いている傾向を発見しました。

侍エンジニア塾は上記3つの成功ポイントを満たすようなサービス設計に磨きをかけております。

cta_under_bnr

「自分のスタイルや目的に合わせて学習を進めたいな」とお考えの方は、ぜひチェックしてみてください。

書いた人

長瀬来

Unityを使ったiOSアプリのリリース、フリマサイト運営の経験があります。

経験した言語はC、C#、Javascript、R、Python、Ruby、PHPなど

言語が好きで、英語や中国、ドイツ語を勉強しました。
将来的には海外で生活したいです。

現在はRuby on Rails5やCocos2dxの勉強を主にしています。

ライターとしては
できるだけ初心者にわかりやすい文章になるように心がけています。

趣味は語学、読書です。

おすすめコンテンツ

まずはここから!初心者でも1から学べるプログラミング入門カリキュラム

転職成功で受講料0円!あなたもプログラミングを学んでエンジニアデビュー