2011-08-19 12 views
7

Istnieje wspólny idiom korzystania podstawienia jak:#with (object) i blok trik

def with clazz, &block 
    yield clazz 
    clazz 
end 

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

Czy istnieje sposób, aby iść dalej i definiować #with mieć możliwość robi:

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

lub nawet:

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

?


UPDATE

Później przypadkowo znalazłem dokładnie to, czego szukałem (rozwiązanie podobne do przyjętego jeden): http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153

UPDATE 2

Został on dodany do cukru-wysoki/dsl w https://github.com/kristianmandrup/sugar-high

UPDATE 3

docille project on Github wykorzystuje ten pomysł bardzo ładnie.

+0

co? Możesz wybrać zmienną bloku tak krótką, jak chcesz. Co byś zaoszczędził? A tak przy okazji, przegapiłeś 'do'. –

+0

Skup się na pytaniu, proszę! Czy to w końcu możliwe? –

+3

"Istnieje wspólny język używania podstawień takich jak" - '[potrzebne źródło]'. –

Odpowiedz

7

Jeśli odnosimy się do sposobu, w jaki Rails ma routingu to myślę, że trzeba zrobić coś takiego

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

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

to jak widzę to się robi w Rails źródło i tak zacząć od spojrzenia w metodzie rozciągania action_pack/lib/action_dispatch/routing/route_set

3

nie jest twój pseudo-Ruby:

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

samo jak przy użyciu 1,9 na tap? Na przykład:

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

Nadal musisz oczywiście wymienić argument blokowy.

+0

Masz rację. Są bardzo podobne. Ale chcę uniknąć wywołań zmiennych przekazywanych do zablokowania, ale bezpośrednio! jak Hash [: a,: b] .some_cool_method {merge! ({: c =>: d})} –

1

można użyć wbudowanego tap rubin:

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

To może być nawet „nadużywane” do wielokrotnego o bjects:

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

Oczywiście obie nie dają ci dokładnie co with zrobi zależności przykład: Blok nie będą oceniane w instancji obiektu. Ale wolę dużo używać tap z wielu obiektów, plus tapself zwrotny, dzięki czemu może być przykuty:

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