Help us understand the problem. What is going on with this article?

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

More than 5 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
finc
健康寿命を伸ばすアプリFiNCの開発・運営を行うモバイルヘルステクノロジーベンチャー
https://finc.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away