2010-06-23 24 views
13

Tôi đã đọc trên RSpec và tôi đã cố gắng tìm ra cách "cần" của RSpec được triển khai như thế nào.Lập trình meta Ruby, làm thế nào để 'làm việc' của RSpec hoạt động?

Ai đó có thể đưa ra một tay về tính chất meta của chức năng này hoạt động như thế nào?

Mã này nằm ở đây:

http://github.com/dchelimsky/rspec/blob/master/lib/spec/expectations/extensions/kernel.rb

TIA,

-daniel

Làm rõ:

target.should == 5 

Làm thế nào mà giá trị mục tiêu có được thông qua cùng với "nên ", lần lượt là" == "'d so với 5?

Trả lời

27

Hãy xem class OperatorMatcher.

Tất cả đều đổ xuống Ruby cho phép bạn thoát khỏi các dấu chấm và dấu ngoặc đơn. Những gì bạn đang thực sự viết là:

target.should.send(:==, 5) 

Đó là, gửi tin nhắn should đến đối tượng target, sau đó gửi tin nhắn == để bất cứ điều gì should lợi nhuận.

Phương pháp should là con khỉ được vá thành Kernel, vì vậy nó có thể được nhận bởi bất kỳ đối tượng nào. Các Matcher trả lại bởi should giữ actual trong trường hợp này là target.

Các Matcher thực hiện các phương pháp == mà không so sánh với expected đó, trong trường hợp này, là số 5. ​​Một cắt giảm ví dụ mà bạn có thể thử tự hỏi:

module Kernel 
    def should 
    Matcher.new(self) 
    end 
end 

class Matcher 
    def initialize(actual) 
    @actual = actual 
    end 

    def == expected 
    if @actual == expected 
     puts "Hurrah!" 
    else 
     puts "Booo!" 
    end 
    end 
end 

target = 4 
target.should == 5 
=> Booo! 

target = 5 
target.should == 5 
=> Hurrah! 
+3

Cảm ơn fo một lời giải thích chút lớn không chỉ trả lời câu hỏi mà còn là một bản tóm tắt hay về một số cơ chế trong Ruby. Đối với những người mới sử dụng Ruby, hãy lưu ý rằng biểu thức cuối cùng trong hàm là ngầm định giá trị trả về, vì vậy phải ở trên trong C++ là Matcher * Kernel :: should() { trả về Matcher mới (this); } –

+0

@Andy Dent: cảm ơn bạn đã nhận xét tích cực –

+2

Đầu tiên: Câu trả lời rất hay, cảm ơn rất nhiều! Hai quan sát nhanh: thay vì định nghĩa "nên" trên mô-đun hạt nhân, bạn có thể làm điều đó trên đối tượng lớp. Tôi thấy nó an toàn hơn, vì nó ít chung chung hơn. Điều thứ hai là bạn không cần metaprogramming để xác định phương thức ==. Bạn chỉ có thể xác định nó như bất kỳ phương pháp bình thường nào khác, để dễ đọc hơn: def == (mong đợi) –

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