2010-08-27 25 views
22

Tôi có một câu hỏi mang tính khái niệm hơn trong Rails ... hoặc Ruby cho vấn đề đó:Khi nào cần gọi "yêu cầu" trong Rails?

Tốt nhất bạn nên gọi ngay trước khi có nhu cầu, nhóm yêu cầu của tôi ở đầu lớp hoặc ở đâu đó trong khởi tạo khi Rails khởi động?

Liệu nó có quan trọng từ quan điểm hiệu suất không? Từ một quan điểm dễ đọc? Nó có tạo sự khác biệt nếu tôi đang sử dụng Rails 3 không?

Cảm ơn!

Trả lời

19

Nếu bạn lo ngại về hiệu suất thì bạn nên yêu cầu mọi thứ trong ngữ cảnh cần thiết để nếu phần đó không được thực hiện, thư viện sẽ không được tải. Mọi cuộc gọi tiếp theo đến require sẽ không có hiệu lực vì tệp đó đã được tải. Điều này kết thúc giống như một cái gì đó dọc theo dòng:

if (user.using_openid?) 
    require 'openid' 

    # ... Do OpenID stuff 
end 

Trong khi điều này hiệu quả hơn về tài nguyên, có thể rất khó xác định sự phụ thuộc của ứng dụng của bạn. Việc khai báo các tính năng này giúp cho người khác duy trì phần mềm rõ ràng. Hãy nhớ rằng "những người khác" luôn bao gồm bản thân tương lai của bạn khi bạn đã quên một số chi tiết về đơn đăng ký của mình.

Bạn về mặt kỹ thuật được phép yêu cầu bất cứ điều gì bất cứ lúc nào, trễ hoặc sớm, nhưng tuyên bố yêu cầu của bạn lên phía trước tốt hơn từ góc độ thiết kế. Nếu bạn thấy rằng có một phần tử chỉ được sử dụng không liên tục và mất một lượng thời gian hoặc bộ nhớ bất thường để tải, thì có lẽ bạn nên ghi tài liệu đó lên phía trước trong tệp yêu cầu của mình. Ví dụ:

require 'library1' 
require 'library2' 
require 'library3' 
require 'library4' 
require 'library5' 

# Other libraries loaded as required: 
# * slowimagelibrary 
# * slowencryptionlibrary 
# * openid 

Có thể cho rằng đây là ít hơn của một vấn đề với bundler vì bạn có thể có đá quý của bạn tuyên bố lên phía trước chính thức hơn và thực tế require cuộc gọi có thể đến sau.

+2

Cảm ơn tadman, điều này phù hợp với những gì tôi đang nghĩ. Kết luận: khả năng đọc là quan trọng hơn hiệu suất ngoại trừ khi sử dụng nặng đòi hỏi. – Cimm

4

Nếu bạn xem xét vanilla Ruby, 'require' chủ yếu được sử dụng trong dòng đầu tiên, bởi vì bạn chắc chắn bạn có quyền truy cập vào những gì bạn cần, và dễ tìm và đọc phụ thuộc bạn cần.

Có một vài trường hợp khi bạn chỉ muốn tải đá quý theo phương pháp, vì điều này không thực sự cần thiết để tập lệnh của bạn hoạt động (ví dụ: hiển thị tùy chọn).

Với Rails, tôi tin rằng nó phụ thuộc vào những gì bạn muốn làm.

Nếu bạn sử dụng Bundler, bạn có thể giả sử đá quý của bạn đã được 'yêu cầu' (bạn có thể ghi đè lên những gì được yêu cầu với tùy chọn: require).

Nếu đó là một số nội dung bạn muốn tự động tải khi máy chủ khởi động (như trình duyệt tính hợp lệ hoặc trình tạo biểu mẫu), thì bạn nên tìm cách thực hiện với cấu hình (autoload_paths và eager_load_paths).

yêu cầu cũng có thể được sử dụng để chỉ tải một phần của đá quý, như phần mở rộng cho đá quý. Sau đó, nó là tất nhiên yêu cầu nơi cấu hình được.

Bạn có thể quan tâm nếu bạn làm việc trong môi trường nhiều luồng, vì chúng là một số vấn đề với điều đó. Sau đó, bạn phải đảm bảo mọi thứ được tải trước khi chủ đề của bạn chạy. (Một cái gì đó giống như hằng số lớp được nạp, nhưng các phương pháp chưa, có một bài viết hay nhưng tôi không thể tìm thấy nó nữa).

Bạn cũng có thể muốn thử {Mô-đun, Hạt nhân}.autoload, Rails sử dụng rộng rãi nó để tải chỉ những gì cần thiết khi truy cập (nhưng nó trông khá xấu xí).

Bạn cũng có thể tự mình hack bằng const_missing (vì vậy điều này có thể làm việc tải xuống đơn giản, nếu bạn chấp nhận cấu trúc). Đây là một ví dụ đơn giản (sẽ không thích hợp cho các lớp lồng nhau).

def Object.const_missing c 
    if (file = Dir["#{c.downcase}.rb"]).size == 1 
    require_relative(file) 
    end 
    if const_defined? c 
    const_get c 
    else 
    super # Object < Module 
    end 
end 

Giới thiệu về hiệu suất, cuộc gọi đến yêu cầu tương đối đắt, vì vậy nếu bạn biết bạn sẽ sử dụng nó, chỉ thực hiện một lần nếu có thể. Tuy nhiên, để quản lý các phụ thuộc phức tạp trong dự án của bạn, bạn có thể cần phải yêu cầu các tệp tương đối. Sau đó, require_relative là cách để sử dụng phiên bản 1.9.

Cuối cùng, đối với một dự án, tôi khuyên bạn nên yêu cầu tất cả trong tệp chính trong lib /, với một số biểu thức Dir["**/*.rb"]. Sau đó bạn hiếm khi cần phải require_relative, bởi vì nó chỉ cần thiết nếu bạn tham chiếu trong phần thân của lớp khác hằng số (tất cả nội dung của các phương thức không được giải quyết, do đó không có vấn đề gì với điều đó).

Một giải pháp khác là xác định các hằng số này trong tệp chính của bạn, nó cũng sẽ cung cấp cho bạn ý tưởng về cấu trúc.

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