I love the autoload functionality of Ruby; tuy nhiên, nó là going away in future versions of Ruby vì nó không bao giờ an toàn chỉ.Tự nạp các lớp trong Ruby mà không có `autoload`
Vì vậy, ngay bây giờ tôi muốn giả vờ nó đã biến mất và viết mã của tôi mà không có nó, bởi thực hiện cơ chế lười tải mình bản thân. Tôi muốn thực hiện nó theo cách đơn giản nhất có thể (Tôi không quan tâm về an toàn luồng ngay bây giờ). Ruby nên cho phép chúng tôi làm điều này.
Hãy bắt đầu bằng việc làm tăng một lớp const_missing
:
class Dummy
def self.const_missing(const)
puts "const_missing(#{const.inspect})"
super(const)
end
end
Ruby sẽ gọi phương thức đặc biệt này khi chúng tôi cố gắng để tham khảo một hằng số dưới 'Dummy' đó là mất tích, ví dụ nếu chúng ta cố gắng tham khảo "Dummy: : Xin chào ", nó sẽ gọi const_missing
với Symbol :Hello
. Đây chính là điều chúng ta cần, vì vậy hãy mang nó hơn nữa:
class Dummy
def self.const_missing(const)
if :OAuth == const
require 'dummy/oauth'
const_get(const) # warning: possible endless loop!
else
super(const)
end
end
end
Bây giờ nếu chúng ta tham khảo "Dummy :: OAuth", nó sẽ đòi hỏi sự "giả/oauth.rb" tập tin đó được dự kiến để xác định " Dummy :: OAuth "hằng số. Có khả năng xảy ra vòng lặp vô tận khi chúng tôi gọi const_get
(vì nó có thể gọi const_missing
nội bộ), nhưng việc bảo vệ chống lại điều đó nằm ngoài phạm vi của câu hỏi này.
Vấn đề lớn là, toàn bộ giải pháp này bị hỏng nếu tồn tại một mô-đun có tên "OAuth" trong không gian tên cấp cao nhất. Tham chiếu "Dummy :: OAuth" sẽ bỏ qua số const_missing
và chỉ trả lại "OAuth" từ cấp cao nhất. Hầu hết các trường Ruby cũng sẽ tạo ra một cảnh báo về vấn đề này:
warning: toplevel constant OAuth referenced by Dummy::OAuth
This was reported as a problem way back in 2003 nhưng tôi không thể tìm thấy bằng chứng cho thấy đội ngũ nòng cốt Ruby đã bao giờ quan tâm về vấn đề này. Ngày nay, các triển khai Ruby phổ biến nhất mang cùng một hành vi.
Vấn đề là const_missing
bị bỏ qua một cách âm thầm với một hằng số trong không gian tên cấp cao nhất. Điều này sẽ không xảy ra nếu "Dummy :: OAuth" được khai báo với chức năng autoload
của Ruby. Bất kỳ ý tưởng làm thế nào để làm việc xung quanh này?
Điều này có vẻ như là một gợi ý ngớ ngẩn, nhưng bạn có thể nhìn vào nguồn C của 'autoload'? Tôi chắc rằng bạn có thể tìm thấy nó ở đâu đó trong nguồn Ruby. Nếu bạn không thể làm điều đó trong Ruby thẳng, có tùy chọn tạo phần mở rộng C (có quyền truy cập vào phần dưới của trình thông dịch). – Linuxios
Đó là một tùy chọn. – mislav
nghe có vẻ giống như một điều bạo lực, nhưng bạn không thể 'remove_const' trên lớp cấp cao nhất? – phoet