Crafting Rails Applications の本を読んでいて、Rails のソース コードを手に入れました。そこで私は考えさせられる RUBY_EVAL の例をいくつか見つけました。
action_controller/metal/renderers.rb はこれを使用して、_write_render_options の本体を構成し、_handle_render_options メソッドを定義します。
def _write_render_options
renderers = _renderers.map do |name, value|
<<-RUBY_EVAL
if options.key?(:#{name})
_process_options(options)
return _render_option_#{name}(options.delete(:#{name}), options)
end
RUBY_EVAL
end
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def _handle_render_options(options)
#{renderers.join}
end
RUBY_EVAL
end
_render_option_#{name} メソッドもオンザフライで定義されます
RENDERERS = {}
def self.add(key, &block)
define_method("_render_option_#{key}", &block)
RENDERERS[key] = block
All._write_render_options
end
eval の代替手段があったように私には思えます。キーに関連付けられた &blocks をハッシュの下に保持しないのはなぜですか? _handle_render_options を呼び出すときに、適切なブロックを選択して評価するのでしょうか? 非効率的な if がたくさんあるメソッド本体を構築するのはなぜですか?
わからない。