Ruby元编程的一些值得注意的地方
避免无限循环的元编程。
写一个函数库时不要使核心类混乱(不要使用monkeypatch)。
代码块形式最好用于字符串插值形式。
当你使用字符串插值形式,总是提供__FILE__和__LINE__,使得你的回溯有意义。
class_eval'defuse_relative_model_naming?;true;end',__FILE__,__LINE__
define_method最好用class_eval{def...}
当使用class_eval(或者其他的eval)以及字符串插值,添加一个注释块使之在插入的时候显示(这是我从rails代码学来的实践):
#fromactivesupport/lib/active_support/core_ext/string/output_safety.rb UNSAFE_STRING_METHODS.eachdo|unsafe_method| if'String'.respond_to?(unsafe_method) class_eval<<-EOT,__FILE__,__LINE__+1 def#{unsafe_method}(*args,&block)#defcapitalize(*args,&block) to_str.#{unsafe_method}(*args,&block)#to_str.capitalize(*args,&block) end#end def#{unsafe_method}!(*args)#defcapitalize!(*args) @dirty=true#@dirty=true super#super end#end EOT end end
避免在元编程中使用method_missing,它使得回溯变得很麻烦,这个习惯不被列在#methods,拼写错误的方法可能也在默默的工作,例如nukes.launch_state=false。考虑使用委托,代理或者是define_method,如果必须这样,使用method_missing,
确保也定义了respond_to_missing?
仅捕捉字首定义良好的方法,像是find_by_*―让你的代码越肯定(assertive)越好。
在语句的最后调用super
delegate到确定的、非魔法方法中:
#bad defmethod_missing?(meth,*args,&block) if/^find_by_(?<prop>.*)/=~meth #...lotsofcodetodoafind_by else super end end #good defmethod_missing?(meth,*args,&block) if/^find_by_(?<prop>.*)/=~meth find_by(prop,*args,&block) else super end end #bestofall,though,wouldtodefine_methodaseachfindableattributeisdeclared