if respond_to?(generate_method, true) send(generate_method, attr_name) else => define_proxy_call true, generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end attribute_method_matchers_cache.clear end
defdefine_proxy_call(include_private, mod, name, send, *extra)#:nodoc: defn = if name =~ NAME_COMPILABLE_REGEXP "def #{name}(*args)" else "define_method(:'#{name}') do |*args|" end
extra = (extra.map!(&:inspect) << "*args").join(", ")
target = if send =~ CALL_COMPILABLE_REGEXP "#{"self."unless include_private}#{send}(#{extra})" else "send(:'#{send}', #{extra})" end
mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 #{defn} #{target} end RUBY end
这里使用代码字符串来实现方法的动态定义,结合我们的例子,这段代码最终会被翻译成:
1 2 3 4
define_method(:clear_name) do|*args| send(:clear_attribute, 'name') end
defmethod_missing(method, *args, &block) if respond_to_without_attributes?(method, true) super else match = match_attribute_method?(method.to_s) match ? attribute_missing(match, *args, &block) : super end end
defattribute_missing(match, *args, &block) __send__(match.target, match.attr_name, *args, &block) end