2012-02-10 27 views
8

Ruby'de basit bir dsl yazıyorum. temizleyici kodunaRuby'de argüman olmadan DSL bloğu

some_method argument do |book| 
    book.some_method_on_book 
    book.some_other_method_on_book :with => argument 
end 

: Birkaç hafta önce ben gibi bir kod dönüştürmek için nasıl kullanıldığını gösteren bazı blog yayını tökezledi

some_method argument do 
    some_method_on_book 
    some_other_method_on_book :with => argument 
end 

hatırlayamıyorum bunu ben değilim nasıl Downsides hakkında emin ama temiz sözdizimi cazip. Bu dönüşüm hakkında bir ipucu var mı?

+0

Başlık değiştirdiğiniz için teşekkürler! İfade ile bazı problemlerim vardı. – dhuCerbin

cevap

9
def some_method argument, &blk 
    #... 
    book.instance_eval &blk 
    #... 
end 

GÜNCELLEME: Ancak, o kitabı atlar ama argüman kullanmak izin vermeyin. Şeffaf olarak kullanmak için onu bir yere taşımalısınız. Ben kitapta kendisi bunu yapmak için öneririz:

class Book 
    attr_accessor :argument 
end 

def some_method argument, &blk 
    #... 
    book.argument = argument 
    book.instance_eval &blk 
    #... 
end 

some_method 'argument' do 
    some_method_on_book 
    some_other_method_on_book argument 
end 
+0

Güncelleme için teşekkürler. Tartışmaları ele alarak daha fazla kişiselleştirme yapmam gerekiyor ama bu yaklaşım güzel sözdizimiyle sonuçlanıyor. – dhuCerbin

7

bu makalede http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation bir göz atın - 'orada (özellikle onun olumsuz yanlarını bağlamında ve onlara olası çözüm belirtilen) yönteminin genel bir bakış, artı Daha fazla okuma için çeşitli faydalı linkler.

Temel olarak, istenen bağlamdaki bloğu yürütmek için instance_eval kullanmakla ilgilidir.

bu tekniğin dezavantajı hakkında konuşan:

Yani onunla sorun nedir? Sorun şu ki, bloklar genellikle genel olarak kapanıyor. Ve aslında tam kapanmalarını beklersin. Ve bu bloğu yazdığınız noktadan bu bloğun tam olarak kapatılmayacağı açık değildir. örnek_eval'i kullandığınızda böyle olur: Bu bloğun kendiliğinden başka bir şeye sıfırlarsınız - bu, bloğun blok dışındaki tüm yerel değişkenleri üzerinde hala bir kapatma olduğunu, ancak yöntem çağrıları için DEĞİL olduğunu belirtir. Sabit aramanın değişip değişmediğini bile bilmiyorum.

example_eval öğesinin kullanılması, bir bloğu okurken, numaralı dilin açık olduğu şekilde dil kurallarını değiştirmez. Bir yöntemin, kelimenin tam anlamıyla neden blokta yaklaşık görebildiğini söyleyebildiğini anlamak için ekstra bir adım düşünmeniz gerekir.

+0

Teşekkürler, downsides hakkında daha fazla kazmam lazım. – dhuCerbin

0

docile gem. Tüm keskin kenarların bakımı sizin için bunu çok kolay hale getirir.