2009-09-21 21 views
54

Làm thế nào là requirerequire_dependency khác nhau?
Làm cách nào để require_dependency tự động tải lại các lớp đang phát triển nhưng require không thể?Yêu cầu, require_dependency và hằng số tải lại liên quan trong Rails như thế nào?

Tôi tìm hiểu mã Rails 'ActiveSupport::Dependencies và dispatcher.rb. Những gì tôi thấy trong mã của require_dependency về cơ bản là thêm các hằng số vào một mảng autoloaded_constants. Nhưng nó được xóa trong clear_application bên trong điều phối viên sau mỗi yêu cầu.

Ai đó có thể đưa ra giải thích rõ ràng hoặc chỉ cho tôi một số tài nguyên sẽ trợ giúp không?

+0

FYI: Việc nạp lại lớp được tự động xử lý trong động cơ (không có gì ngoài plugin với ứng dụng/thư mục), giống như trong ứng dụng bình thường. –

+0

Cảm ơn, Vâng, tôi biết điều đó. Nhưng sau đó điều này dẫn đến câu hỏi khác của tôi: Tôi có thể sử dụng các plugin khác bên trong plugin của mình không? Nói rằng, tôi muốn sử dụng plugin act_as_xxx trong plugin của riêng mình, tôi có thể chỉ đặt act_as_xxx bên trong thư mục plugin/nhà cung cấp plugin của mình và sau đó thêm đường dẫn đến $ LOAD_PATH không? Tôi đoán tôi nên hỏi điều này trong một thread tho, nó không liên quan đến câu hỏi ban đầu của tôi. – wei

Trả lời

108

require (và anh em họ của nó load) là các phương pháp cốt lõi của Ruby. require_dependency là một phương pháp giúp Rails xử lý vấn đề về quản lý phụ thuộc. Dài câu chuyện ngắn, nó cho phép Rails để tải lại các lớp học trong chế độ phát triển để bạn không phải khởi động lại máy chủ mỗi khi bạn thực hiện một thay đổi mã. Khung Rails sẽ require_dependency mã của bạn để nó có thể theo dõi và tải lại khi thay đổi được thực hiện. Ruby require tiêu chuẩn không làm điều đó. Là một nhà phát triển ứng dụng (hoặc plugin/engine), bạn không cần phải lo lắng về require_dependency vì điều này hoàn toàn là nội bộ đối với Rails.

Sự kỳ diệu của quá trình tải lớp Rails nằm trong mô-đun ActiveSupport :: Dependencies. Mã này mở rộng hành vi Ruby mặc định để cho phép mã bên trong ứng dụng Rails của bạn tự động tải các mô-đun (bao gồm các lớp kế thừa từ Mô-đun) bằng cách sử dụng quy ước đặt tên đường dẫn và tệp của Rails. Điều này giúp loại bỏ sự cần thiết của lập trình viên để xả mã của họ bằng các cuộc gọi require giống như bạn sẽ làm trong một ứng dụng Ruby đơn giản.

Để đặt theo cách khác, điều này cho phép bạn xác định class Admin::User bên trong tệp app/models/admin/user.rb và có Rails biết bạn đang nói gì khi gọi Admin::User.new từ một phần khác của ứng dụng như bộ điều khiển. Nếu không có ActiveSupport :: Các phụ thuộc liên quan đến bạn sẽ phải tự tay require mọi thứ bạn cần.

Nếu bạn đến từ một ngôn ngữ được gõ tĩnh như C#, Java, v.v ... thì điều này có thể là một bất ngờ: Mã Rails không được tải cho đến khi cần. Ví dụ: lớp mô hình User không được xác định và user.rb không được tải cho đến SAU KHI bạn cố gắng gọi User.whatever_method_here. Rails ngăn Ruby khỏi phàn nàn về hằng số bị thiếu, tải mã cho User và sau đó cho phép Ruby tiếp tục như bình thường.

Mặc dù tôi không thể nói cho nhu cầu cụ thể của bạn, tôi sẽ rất ngạc nhiên nếu bạn thực sự cần sử dụng phương thức require_dependency từ bên trong plugin hoặc công cụ. Nếu bạn theo các quy ước của Rails, bạn cũng không cần phải tinh chỉnh $ LOAD_PATH bằng tay. Đây không phải là "cách Rails".

Trong thế giới của Ruby và Rails cũng đơn giản và rõ ràng là chìa khóa. Nếu tất cả các bạn muốn làm là viết một plugin hoặc động cơ và bạn đã lặn sâu vào internals sau đó bạn có thể xem xét tiếp cận vấn đề của bạn từ một góc độ khác nhau. Ruột của tôi nói với tôi rằng bạn có thể đang cố gắng làm điều gì đó không cần thiết phức tạp. Nhưng sau đó một lần nữa, tôi không có đầu mối những gì bạn đang làm chính xác !! :)

16

require_dependency rất hữu ích trong công cụ khi bạn muốn mở lại một lớp không được xác định trong công cụ của bạn (ví dụ: trong một công cụ khác hoặc ứng dụng Rails) và được tải lại.Trong trường hợp nào đó giống như thế này hoạt động:

# app/controllers/my_engine/documents_controller.rb 
require_dependency MyEngine::Engine.root.join('app', 'controllers', 'my_engine', 'documents_controller').to_s 

module MyEngine 
    class DocumentsController 
    def show 
     render :text => 'different' 
    end 
    end 
end 
Các vấn đề liên quan