2012-02-10 19 views
8

Tôi đang viết một dsl đơn giản bằng ruby. Vài tuần trước, tôi tình cờ gặp một số bài viết trên blog, trong đó cho thấy làm thế nào để chuyển đổi mã như:Khối DSL không có đối số trong ruby ​​

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

vào mã sạch hơn:

some_method argument do 
    some_method_on_book 
    some_other_method_on_book :with => argument 
end 

Tôi không thể nhớ làm thế nào để làm điều này và tôi không chắc chắn về nhược điểm nhưng cú pháp sạch hơn là hấp dẫn. Có ai có manh mối về sự biến đổi này không?

+0

Cảm ơn bạn đã thay đổi tiêu đề! Tôi đã có một số vấn đề với từ ngữ. – dhuCerbin

Trả lời

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

CẬP NHẬT: Tuy nhiên, việc bỏ qua cuốn sách đó không cho phép bạn sử dụng đối số. Để sử dụng nó một cách minh bạch, bạn phải vận chuyển nó một cách bình thường. Tôi đề nghị để làm điều đó trên chính cuốn sách:

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

Cảm ơn bạn đã cập nhật. Tôi cần phải làm một số tùy biến hơn với các đối số xử lý nhưng kết quả aproach này trong cú pháp tốt đẹp. – dhuCerbin

7

Hãy xem bài viết này http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation - có một tổng quan về các phương pháp (được nêu cụ thể trong bối cảnh nhược điểm của nó và khả năng giải pháp cho họ), cộng với có' một số liên kết hữu ích để đọc thêm.

Về cơ bản, đó là về việc sử dụng instance_eval để thực thi khối trong ngữ cảnh mong muốn.

Nói về nhược điểm của kỹ thuật này:

Vì vậy, vấn đề với nó là những gì? Vâng, vấn đề là các khối là thường đóng cửa. Và bạn mong đợi họ thực sự bị đóng cửa hoàn toàn. Và nó không rõ ràng từ điểm mà bạn viết khối rằng khối đó có thể không phải là một đóng cửa đầy đủ. Đó là những gì xảy ra khi bạn sử dụng instance_eval: bạn đặt lại chính khối đó thành thứ gì đó khác - điều này có nghĩa là khối vẫn đóng cửa trên tất cả các biến số cục bộ bên ngoài khối, nhưng KHÔNG cho cuộc gọi phương thức. Tôi thậm chí không biết nếu tra cứu liên tục có thay đổi hay không.

Sử dụng instance_eval thay đổi các quy tắc cho ngôn ngữ theo cách mà không rõ ràng khi đọc một khối. Bạn cần phải suy nghĩ thêm một bước để tìm ra chính xác lý do tại sao một phương thức gọi là bạn có thể lexically xem xung quanh khối thực sự không thể được gọi từ bên trong khối.

+0

Cảm ơn, tôi đã digg nhiều hơn về những nhược điểm. – dhuCerbin

0

Kiểm tra đá quý docile. Nó sẽ chăm sóc của tất cả các cạnh sắc nét, làm cho điều này rất dễ dàng cho bạn.

Các vấn đề liên quan