2011-08-19 84 views
7

存在使用替代像一个常见的成语:#with(对象)块招

def with clazz, &block 
    yield clazz 
    clazz 
end 

with Hash.new |hash| 
    hash.merge!{:a => 1} 
end 

有没有办法走的更远,并定义#with有这样的可能性:

with Hash.new |hash| 
    merge!{:a => 1} 
end 

甚至:

with Hash.new do 
    merge!{:a => 1} 
end 


UPDATE

后来无意中,我发现正是我一直在寻找(解决类似接受一个): http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153

更新加入2

到糖高/ dsl https://github.com/kristianmandrup/sugar-high

更新3

docille project on Github利用这个想法非常漂亮。

+0

为了什么?你可以选择你的块变量尽可能短。你会节省什么?顺便说一句,你错过了'做'。 –

+0

请关注问题!终于有可能吗? –

+3

“有一个使用替换的常见习语,比如” - '[需要的引证]'。 –

回答

7

如果你指的是在Rails会路由那么我认为你需要做这样的事情

def with(instance, &block) 
    instance.instance_eval(&block) 
    instance 
end 

with(Hash.new) do 
    merge!({:a => 1}) 
    merge!({:b => 1}) 
end 

这是我可以看到它正在Rails的源反正看开始做的方式在action_pack/lib/action_dispatch/routing/route_set

3

是不是你的伪红宝石:

with Hash.new do |hash| 
    merge!{:a => 1} 
end 

同样的事情,使用1.9的tap?例如:

>> x = Hash[:a, :b].tap { |h| h.merge!({:c => :d}) } 
=> {:a=>:b, :c=>:d} 

当然你仍然需要命名block参数。

+0

你说得对。他们非常相似。但我想避免调用传递给块的变量,但直接!如Hash [:a,:b] .some_cool_method {merge!({:c =>:d})}} –

1

抽签方法可以使用红宝石内置tap

Hash.new.tap do |hash| 
    hash.merge! a: 1 
end 

这甚至可以是多个O“被虐待” bjects:

[one_long_name, another_long_name].tap do |(a,b)| 
    a.prop = b.prop 
end 

当然都没有给你什么with会根据你的例子做:该块将不是对象的实例中进行评估。但我更喜欢大量使用tap有多个对象,加上tap回报self,因此它可以被链接:

[one_long_name, another_long_name].tap {|(a,b)| a.prop = b.prop }.inspect