Ruby

class_evalの第1引数に文字列を渡したときの挙動についてメモ

More than 3 years have passed since last update.


class_eval(code, file, lineno)


eval.rb

class Shino

def self.shino
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def name
puts 'fumi'
raise
end
RUBY
end
end

Shino.shino
s = Shino.new
s.name
# => fumi
# eval.rb:6:in `name': unhandled exception
# from eval.rb:14:in `<main>'
#
# shell returned 1


第1引数に渡された文字列は、クラス定義の中のコードであるように実行される。上記の例だとShinoクラスのインスタンスメソッドnameが定義される。

第2引数と第3引数はstacktraceのときに利用される。

第2引数に__FILE__、第3引数に__LINE__ + 1としておくとわかりやすい。


参考)

http://ref.xaio.jp/ruby/classes/module/class_eval


利用例)

ActiveSupport::Callbacks::ClassMethods#define_callbacksで利用されている。


activesupport/lib/active_support/callbacks.rb

module ActiveSupport

module Callbacks
module ClassMethods
def define_callbacks(*names)
options = names.extract_options!

names.each do |name|
class_attribute "_#{name}_callbacks"
set_callbacks name, CallbackChain.new(name, options)

module_eval <<-RUBY, __FILE__, __LINE__ + 1
def _run_
#{name}_callbacks(&block)
_run_callbacks(_
#{name}_callbacks, &block)
end
RUBY
end
end
end
end
end