Rubyでevalメソッドを使う方法【初心者向け】

初心者向けにRubyでevalを使う方法について解説しています。引数で渡された文字列をコードとして実行することができます。どういう場面で使うのか、実際のソースコードの書き方も含めて勉強していきましょう。

TechAcademyマガジンはオンラインのプログラミングスクールTechAcademy [テックアカデミー]が運営する教育×テクノロジーのWebメディアです。初心者でもすぐ勉強できる記事が2,000以上あります。

Rubyでevalを使う方法について解説します。

Rubyについてそもそもよく分からないという方は、Rubyとは何なのか解説した記事をまずご覧ください。

 

なお本記事は、TechAcademyのWebアプリケーションオンラインブートキャンプの内容をもとに紹介しています。

 

田島悠介

今回は、Rubyに関する内容だね!

大石ゆかり

どういう内容でしょうか?

田島悠介

evalを使う方法について詳しく説明していくね!

大石ゆかり

お願いします!

 

evalとは

evalとは、引数で渡した文字列をRubyのプログラムとして実行するメソッドです。

例えば、動的なメソッドの実装や、異常検知の実装などに利用ができます。

複数の似たようなメソッドが存在し、名前がそれぞれ違う場合、通常であれば以下のように記述をするはずです。

def method_a
  puts "method_a"
end

def method_b
  puts "method_b"
end

mtehod_a # method_aの実行
method_b # method_bの実行

 

evalを使用する事で、以下のように実装ができるようになります。

def method(name)
  eval("puts \"method_#{name}\"")
end

method("a")
method("b")

 

evalの書き方

evalの引数は以下になります。

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

必須なのは第一引数で、第二引数はBindingオブジェクト、第三引数はファイル名、第四引数は行数が指定できます。

第三引数、第四引数を与えた場合、どこに書かれているかを見せかける事ができるようになります。

eval("puts a", nil, "sample.rb", 10)

# 変数aは定義されていないためエラー
# sample.rb:10:in `<main>': undefined local variable or method `a' for main:Object (NameError)
# from 10.rb:1:in `eval'
# from 10.rb:1:in `<main>'

Bindingオブジェクトは、変数やメソッドの有効範囲(スコープ)を与えます。
例えばメソッドの中の変数にアクセスさせたい場合などです。

def sample
  a = "a"
  # Bindingオブジェクトを生成
  binding
end

eval("p a", sample)
# sampleメソッドの変数 a にアクセスするため、エラーにならず、 a と表示される

 

[PR] Rubyのプログラミングで挫折しない学習方法を動画で公開中

実際に書いてみよう

複数の攻撃方法がある中、ランダムに選択し、相手を攻撃する、というサンプルを見てみましょう。

ソースコード

class Character

  attr_accessor :hp

  def initialize(name)
    @name = name
    @hp = 100
  end

  # hpの減算処理
  def decrese_hp(damage)
    @hp = @hp - damage
    p "#{@name}は#{damage}を受けた、HP:#{@hp}"
  end

  # attack_a ~ c は、それぞれ与えるダメージを返すのみ
  def attack_a
    10
  end

  def attack_b
    5
  end

  def attack_c
    1
  end

end

# 2つのCharacterオブジェクトを生成
a = Character.new("A")
b = Character.new("B")

random = Random.new

loop do

  # a~c のいずれかの選択
  attack = ["a","b","c"]

  # 乱数から、動的に攻撃方法を選択し、相手を攻撃
  eval("a.decrese_hp(b.attack_#{attack[rand(attack.length)]})")
  eval("b.decrese_hp(a.attack_#{attack[rand(attack.length)]})")

  # どちらかのHPが0以下になったら処理を終了
  if a.hp <= 0 || b.hp <= 0
    break
  end

end

実行結果

"Aは1を受けた、HP:21"
"Bは5を受けた、HP:31"
"Aは5を受けた、HP:16"
"Bは10を受けた、HP:21"
"Aは5を受けた、HP:11"
"Bは10を受けた、HP:11"
"Aは10を受けた、HP:1"
"Bは10を受けた、HP:1"
"Aは10を受けた、HP:-9"
"Bは10を受けた、HP:-9"

このように、evalを使用することで、文字列から動的にメソッドを実行する、という事が実現できます。

 

回答してくれたメンター

中廣 誠

職種: WEBエンジニア

過去の開発実績・業務内容:
一部上場企業にて、WEBアプリケーションの受託開発、自社WEBサービス開発、自社ゲーム開発に従事
現在はフリーで活動し、ECサイト開発/運営、課題を解決するためのシステムコンサルタントなどを実施

趣味など
フリーでの活動を期に沖縄へ移住したので、海でのスキンダイビング、釣りなどを趣味にしています。

 

大石ゆかり

内容分かりやすくて良かったです!

田島悠介

ゆかりちゃんも分からないことがあったら質問してね!

大石ゆかり

分かりました。ありがとうございます!

TechAcademyでは初心者でも最短4週間でエンジニアになれるRuby on Railsオンラインブートキャンプを開催しています。

現役エンジニアがパーソナルメンターとして受講生に1人ずつつき、マンツーマンのメンタリングで学習をサポートし、最短4週間でオリジナルWebサービスを開発することが可能です。

また、現役エンジニアから学べる無料のプログラミング体験会も実施しているので、ぜひ参加してみてください。