詩歌rails之 Delegate

詩歌rails之 Delegate

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. end
06.
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. end
10.
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. end
18. EOS
19. end
20.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" end
03. def goodbye() "goodbye" end
04.end
05.
06.class Foo < ActiveRecord::Base
07. delegate :hello, :goodbye, :to => :greeter
08.end
09.
10.Foo.new.hello # => "hello"
11.Foo.new.goodbye # => "goodbye"

增加:prefix => true:

1.class Foo < ActiveRecord::Base
2. delegate :hello, :goodbye, :to => :greeter, :prefix => true
3.end
4.
5.Foo.new.greeter_hello # => "hello"
6.Foo.new.greeter_goodbye # => "goodbye"

自定義前綴名:

1.class Foo < ActiveRecord::Base
2. delegate :hello, :goodbye, :to => :greeter, :prefix => :foo
3.end
4.
5.Foo.new.foo_hello # => "hello"
6.Foo.new.foo_goodbye # => "goodbye"

ruby的動態性再一次發揮了強大的功能!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章