Я читал книгу «Ремесла Rails Applications» и получил мои руки на исходный код Rails. Там я нашел несколько примеров RUBY_EVAL, которые заставляли меня думать: почему они это сделали?Почему 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 _ # {имя} методы определяются на лету, а
RENDERERS = {}
def self.add(key, &block)
define_method("_render_option_#{key}", &block)
RENDERERS[key] = block
All._write_render_options
end
Мне кажется, что есть альтернативы Eval. Почему бы не просто сохранить эти блоки &, связанные с ключами под хэш? Поэтому при вызове _handle_render_options мы бы выбрали правильный блок и оценили его? Зачем строить тело метода с большим количеством if, которое неэффективно, не так ли?
У меня его нет.
Почему бы не использовать 'define_method' везде? – user2398029
'define_method' немного дороже, потому что он сохраняет привязку, которая должна быть активирована при вызове. Я не уверен, хотя, если это все еще актуально в последних версиях Ruby, скорее всего, нет. –