Delegate是一种应用composite来代替extend的机制,可以有效地降低代码的耦合性。
Rails 2.2增加了delegate方法,可以十分方便地实现delegate机制。
01.def delegate(*methods) 02. options = methods.pop 03. unless options.is_a?(Hash) && to = options[:to] 04. raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."05. end06. 07. if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/ 08. raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."09. end10. 11. prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"12. 13. methods.each do |method| 14. module_eval(<<-EOS, "(__DELEGATION__)", 1) 15. def #{prefix}#{method}(*args, &block) 16. #{to}.__send__(#{method.inspect}, *args, &block) 17. end18. EOS19. end20.end
delegate方法首先检查传入的参数,正确参数形式为:method1, :method2, ..., :methodN, :to => klass[, :prefix => prefix]
delegate要求参数的最后必须是一个Hash,:to表示需要代理的类,:prefix表示代理的方法是否要加前缀,如果:prefix => true,则代理的方法名为klass_method1,
klass_method2, ..., klass_methodN,如果:prefix => prefix (prefix为string),则代理的方法名为prefix_method1, prefix_method2, ..., prefix_methodN。
最终通过module_eval动态生成每个方法定义。通过__send__方法调用:to类的方法。
来看看调用的例子:
简单的调用:
01.class Greeter < ActiveRecord::Base 02. def hello() "hello" end03. def goodbye() "goodbye" end04.end05. 06.class Foo < ActiveRecord::Base 07. delegate :hello, :goodbye, :to => :greeter08.end09. 10.Foo.new.hello # => "hello" 11.Foo.new.goodbye # => "goodbye"
增加:prefix => true:
1.class Foo < ActiveRecord::Base 2. delegate :hello, :goodbye, :to => :greeter, :prefix => true3.end4. 5.Foo.new.greeter_hello # => "hello" 6.Foo.new.greeter_goodbye # => "goodbye"
自定义前缀名:
1.class Foo < ActiveRecord::Base 2. delegate :hello, :goodbye, :to => :greeter, :prefix => :foo3.end4. 5.Foo.new.foo_hello # => "hello" 6.Foo.new.foo_goodbye # => "goodbye"
ruby的动态性再一次发挥了强大的功能!
转自:http://www.cnblogs.com/orez88/articles/1717438.html