詩歌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的動態性再一次發揮了強大的功能!