2010-03-22 32 views
40

Tôi đang học cách sử dụng class_eval trong các mô-đun (tôi khá quen thuộc với class_eval) và đã xem qua this helpful class in resource_controller. Trong đó họ có những thứ như thế này:Class_eval << - "end_eval", __FILE__, __LINE__ có nghĩa là gì trong Ruby?

class_eval <<-"end_eval", __FILE__, __LINE__ 

    def #{block_accessor}(*args, &block) 
    unless args.empty? && block.nil? 
     args.push block if block_given? 
     @#{block_accessor} = [args].flatten 
    end 

    @#{block_accessor} 
    end 

end_eval 

__FILE____LINE__ làm trong bối cảnh đó? Tôi biết __FILE__ tham chiếu đến tệp hiện tại, nhưng toàn bộ điều đó làm gì chính xác? Không thực sự biết cách tìm kiếm điều đó :).

Trả lời

50

__FILE____LINE__ là loại hằng số động giữ tệp và dòng hiện đang thực thi. Chuyển chúng vào đây cho phép các lỗi báo cáo đúng vị trí của chúng.

instance_eval <<-end_eval, __FILE__, __LINE__ 
    def foo 
    a = 123 
    b = :abc 
    a.send b 
    end 
end_eval 

foo 

Khi bạn chạy này

$ ruby foo.rb 
foo.rb:5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) 
    from foo.rb:5:in `foo' 
    from foo.rb:11 

Lưu ý nó nói các tập tin và dòng # 5 mặc dù đó chỉ là văn bản trong một eval. Nếu không có các tập tin/dòng lừa đầu ra sẽ như thế này:

$ ruby foo.rb 
(eval):5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) 
    from (eval):5:in `foo' 
    from foo.rb:11 

Dấu vết ngăn xếp chỉ đơn giản là hiển thị (eval) không hữu ích.

+1

Có thể nói rằng việc sử dụng 'define_method' thay vì sẽ không cần loại thủ thuật này, cộng với nó sẽ không mở lỗ hổng bảo mật (xem http://stackoverflow.com/questions/3003328/how-do-i-use-class-eval/3003509#3003509) –

3

<< là khởi đầu của heredoc. Dòng đó là bắt đầu của một chuỗi nhiều dòng. Chuỗi được đánh giá để tạo hàm. Hàm class_eval sử dụng __FILE__ và __LINE__ để thêm thông tin gỡ lỗi.

+1

Nhưng nhưng nhưng ... không phải là bạn trình hướng dẫn chơi golf từ golf tình trạng hỗn loạn? Bạn nên biết Ruby như mặt sau của bàn tay của bạn! :-D (Đó là một lời nhận xét về sự mơ hồ của câu nói của bạn về hành vi của 'class_eval' là gì. Nếu ý định của bạn không có vẻ không chắc chắn, tôi lấy lại bình luận của tôi.) –

+0

Haha ... Tôi chưa bao giờ cần chức năng đó vì nó quá nhiều ký tự. –

+0

loại thông tin gỡ lỗi nào? Làm thế nào để tôi sử dụng nó? –

2

Cũng xin lưu ý rằng cần tránh sử dụng các dây buộc eval nếu có thể. Trong trường hợp cụ thể của bạn, thay thế #class_eval với #class_exec là có thể, và nên được ưa thích:

class_exec do 
    define_method block_accessor do |*args, &block| 
    unless args.empty? && block.nil? 
     args.push block if block_given? 
     instance_variable_set "@#{block_accessor}", [args].flatten 
    end 
    instance_variable_get "@#{block_accessor}" 
    end 
end 
Các vấn đề liên quan