诗歌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的动态性再一次发挥了强大的功能!
莫愁前路无知己,天下无人不识君。