Cách tốt nhất để yêu cầu tất cả các tệp từ một thư mục trong ruby là gì?
Cách tốt nhất để yêu cầu tất cả các tệp từ một thư mục trong ruby là gì?
Câu trả lời:
Làm thế nào về:
Dir["/path/to/directory/*.rb"].each {|file| require file }
require
không bị nhầm lẫn bởi sự hiện diện hay vắng mặt của .rb
phần mở rộng. Đã thử nghiệm trên MRI 1.8.7-p374, 2.1.5 và 2.2.0 được thử nghiệm. Truyền thuyết đô thị này đến từ Rails, nơi tự động tải "thông minh" thể hiện hành vi mà ông mô tả trong các phiên bản cũ hơn (và vẫn có thể thể hiện nó).
Nếu đó là một thư mục liên quan đến tệp yêu cầu (ví dụ: bạn muốn tải tất cả các tệp trong thư mục lib):
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
Chỉnh sửa: Dựa trên các bình luận bên dưới, một phiên bản cập nhật:
Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
__dir__
thay vì File.dirname(__FILE__)
.
require_relative
để yêu cầu tất cả các tập tin trong một thư mục?
Hãy thử đá quý allow_all:
Nó cho phép bạn đơn giản:
require_all 'path/to/directory'
require_all
độ phân giải phụ thuộc theo chu kỳ hoạt động xung quanh một vấn đề trong mã nguồn của bạn: bạn có các tệp nguồn Ruby không yêu cầu phụ thuộc của chúng. Điều này sẽ đóng cửa khi tải dao mổ, cam kết bạn sẽ tải tất cả hoặc không có gì. Đó không phải là vấn đề trong các thư viện nhỏ, nhưng đó là một quyết định mà bạn nên đưa ra một cách có ý thức.
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
Nếu bạn không loại bỏ phần mở rộng thì cuối cùng bạn có thể yêu cầu cùng một tệp hai lần (ruby sẽ không nhận ra rằng "foo" và "foo.rb" là cùng một tệp). Yêu cầu cùng một tệp hai lần có thể dẫn đến cảnh báo giả (ví dụ: "cảnh báo: hằng số đã khởi tạo").
require "foo.rb"; require "foo";
sẽ tải foo.rb
chỉ một lần.
require
không bị nhầm lẫn bởi sự hiện diện hay vắng mặt của .rb
phần mở rộng. Đã thử nghiệm trên MRI 1.8.7-p374, 2.1.5 và 2.2.0. Truyền thuyết đô thị này đến từ Rails, nơi tự động tải "thông minh" thể hiện hành vi được mô tả trong các phiên bản cũ hơn (và vẫn có thể thể hiện nó).
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
hoặc cách khác, nếu bạn muốn phạm vi các tệp để tải vào các thư mục cụ thể:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
giải trình:
Dir.glob lấy một khối làm đối số.
phương thức (: Yêu cầu) sẽ trả về phương thức yêu cầu.
& method (: Yêu cầu) sẽ chuyển đổi phương thức thành một khối.
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )
loại bỏ sự phụ thuộc vào nền tảng (chẳng hạn như '/' hoặc '\'). Hoạt động tốt. Cảm ơn.
Cách tốt nhất là thêm thư mục vào đường dẫn tải và sau đó require
là tên cơ sở của mỗi tệp. Điều này là do bạn muốn tránh việc vô tình yêu cầu cùng một tệp hai lần - thường không phải là hành vi dự định. Một tập tin sẽ được tải hay không phụ thuộc vào việc bạn require
đã thấy đường dẫn được chuyển đến trước đó hay chưa. Ví dụ, phiên irb đơn giản này cho thấy rằng bạn có thể yêu cầu và tải cùng một tệp hai lần.
$ irb
irb(main):001:0> require 'test'
=> true
irb(main):002:0> require './test'
=> true
irb(main):003:0> require './test.rb'
=> false
irb(main):004:0> require 'test'
=> false
Lưu ý rằng hai dòng đầu tiên trả về true
có nghĩa là cùng một tệp đã được tải cả hai lần. Khi các đường dẫn được sử dụng, ngay cả khi các đường dẫn trỏ đến cùng một vị trí, require
không biết rằng tệp đã được yêu cầu.
Thay vào đó, chúng tôi thêm một thư mục vào đường dẫn tải và sau đó yêu cầu tên cơ sở của từng tệp * .rb bên trong.
dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
Nếu bạn không quan tâm đến việc tệp được yêu cầu nhiều lần, hoặc ý định của bạn chỉ là tải nội dung của tệp, có lẽ load
nên được sử dụng thay vì require
. Sử dụng tải trong trường hợp này, vì nó thể hiện tốt hơn những gì bạn đang cố gắng thực hiện. Ví dụ:
Dir["/path/to/directory/*.rb"].each {|file| load file }
Thay vì nối các đường dẫn như trong một số câu trả lời, tôi sử dụng File.expand_path
:
Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
Cập nhật:
Thay vì sử dụng, File.dirname
bạn có thể làm như sau:
Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
require file
end
Trường hợp ..
dải tên tệp của __FILE__
.
File.expand_path
Rails.root.join
Câu trả lời khác nhau cũng hoạt động nếu bạn đang ở trong đường ray.
Trong Rails, bạn có thể làm:
Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Cập nhật: Đã sửa với đề xuất của @Jiggneshh Gohel để xóa dấu gạch chéo.
Rails.root.join('/lib')
không tạo đường dẫn chính xác. Tôi tìm thấy cái này để hoạt động chính xác:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Và những gì về : require_relative *Dir['relative path']
?
require_relative *Dir['*.rb']
làm việc, nếu chỉ có một tập lệnh ruby. Nhưng nếu tìm thấy nhiều tập lệnh ruby, bạn sẽ nhận đượcrequire_relative': wrong number of arguments (4 for 1) (ArgumentError)