Apa cara terbaik untuk meminta semua file dari direktori di ruby?
Apa cara terbaik untuk meminta semua file dari direktori di ruby?
Jawaban:
Bagaimana tentang:
Dir["/path/to/directory/*.rb"].each {|file| require file }
require
tidak bingung dengan ada atau tidaknya .rb
ekstensi. Diuji pada MRI 1.8.7-p374, 2.1.5 dan 2.2.0 diuji. Legenda urban ini berasal dari Rails, di mana autoloading "pintar" menunjukkan perilaku yang ia gambarkan dalam versi yang lebih lama (dan mungkin masih menunjukkannya).
Jika itu adalah direktori relatif terhadap file yang memerlukan (misalnya Anda ingin memuat semua file di direktori lib):
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
Sunting: Berdasarkan komentar di bawah, versi yang diperbarui:
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__
sebagai gantinya File.dirname(__FILE__)
.
require_relative
semua file dalam direktori?
Coba permata require_all:
Ini memungkinkan Anda untuk:
require_all 'path/to/directory'
require_all
resolusi dependensi siklik mengatasi masalah dalam kode sumber Anda: Anda memiliki file sumber Ruby yang tidak memerlukan dependensinya. Ini menutup pintu pada pemuatan pisau bedah, membuat Anda melakukan pemuatan semua atau tidak sama sekali. Itu bukan masalah di perpustakaan kecil, tapi itu keputusan yang harus Anda buat secara sadar.
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
Jika Anda tidak menghapus ekstensi, maka Anda mungkin membutuhkan file yang sama dua kali (ruby tidak akan menyadari bahwa "foo" dan "foo.rb" adalah file yang sama). Membutuhkan file yang sama dua kali dapat menyebabkan peringatan palsu (mis. "Peringatan: sudah diinisialisasi konstan").
require "foo.rb"; require "foo";
akan dimuat foo.rb
sekali saja.
require
tidak bingung dengan ada atau tidaknya .rb
ekstensi. Diuji pada MRI 1.8.7-p374, 2.1.5 dan 2.2.0. Legenda urban ini berasal dari Rails, di mana autoloading "pintar" menunjukkan perilaku yang dijelaskan dalam versi lama (dan mungkin masih menunjukkannya).
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
atau sebagai alternatif, jika Anda ingin mengatur ruang lingkup file untuk dimuat ke folder tertentu:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
penjelasan:
Dir.glob mengambil blok sebagai argumen.
metode (: wajib) akan mengembalikan metode yang diperlukan.
& metode (: wajib) akan mengonversi metode menjadi blok.
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )
menghilangkan ketergantungan pada platform (seperti '/' atau '\'). Bekerja dengan baik. Terima kasih.
Cara terbaik adalah menambahkan direktori ke path memuat dan kemudian require
nama dasar setiap file. Ini karena Anda ingin menghindari secara tidak sengaja memerlukan file yang sama dua kali - sering kali bukan perilaku yang diinginkan. Apakah suatu file akan dimuat atau tidak tergantung pada apakah require
telah melihat jalur yang dilewati sebelumnya. Misalnya, sesi irb sederhana ini menunjukkan bahwa Anda dapat secara keliru meminta dan memuat file yang sama dua kali.
$ 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
Perhatikan bahwa dua baris pertama kembali yang true
berarti file yang sama dimuat dua kali. Saat jalur digunakan, bahkan jika jalur menunjuk ke lokasi yang sama, require
tidak tahu bahwa file itu sudah diperlukan.
Di sini, sebagai gantinya, kami menambahkan direktori ke jalur pemuatan dan kemudian memerlukan nama dasar setiap file * .rb di dalamnya.
dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
Jika Anda tidak peduli dengan file yang diminta lebih dari satu kali, atau niat Anda hanya untuk memuat konten file, mungkin load
sebaiknya digunakan saja require
. Gunakan beban dalam kasus ini, karena lebih baik mengekspresikan apa yang Anda coba capai. Sebagai contoh:
Dir["/path/to/directory/*.rb"].each {|file| load file }
Alih-alih menyatukan jalur seperti dalam beberapa jawaban, saya menggunakan File.expand_path
:
Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
Memperbarui:
Alih-alih menggunakan File.dirname
Anda bisa melakukan hal berikut:
Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
require file
end
Di mana ..
strip nama file __FILE__
.
File.expand_path
Rails.root.join
jawaban juga berfungsi jika Anda berada di rel.
Di Rails, Anda dapat melakukan:
Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Pembaruan: Diperbaiki dengan saran dari @Jiggneshh Gohel untuk menghapus garis miring.
Rails.root.join('/lib')
tidak menghasilkan jalur yang benar. Saya menemukan ini bekerja dengan benar:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Dan bagaimana dengan require_relative *Dir['relative path']
:?
require_relative *Dir['*.rb']
bekerja, jika hanya ada satu skrip ruby. Tetapi jika beberapa skrip ruby ditemukan, Anda dapatrequire_relative': wrong number of arguments (4 for 1) (ArgumentError)