Menurut Beliung, ekstensi .rb adalah opsional. Secara teknis ini mengubah arti: "memerlukan 'foo.rb'" memerlukan foo.rb, sedangkan "membutuhkan 'foo'" mungkin memerlukan foo.rb, foo.so atau foo.dll.
Sam Stokes
28
Ada gotcha yang halus untuk tidak membuka ekstensi. Jika beberapa bagian lain dari panggilan kode memerlukan 'foo' maka ruby akan memuat file yang sama lagi, yang dapat menyebabkan kesalahan palsu. Saya menambahkan jawaban saya sendiri yang menjelaskan hal itu dan menunjukkan cara menghapus ekstensi.
Pete Hodgson
4
@Pete, apakah ini masih benar? Lihat komentar Rene di bawah ini.
Andres Riofrio
5
Ini mungkin jelas, tetapi perlu dicatat bahwa menjatuhkan .rb juga akan memerlukan file non-.rb dalam direktori, yang mungkin tidak diinginkan.
user2398029
10
Saran @ PeteHodgson tidak akurat. Ruby requiretidak bingung dengan ada atau tidaknya .rbekstensi. 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).
sheldonh
345
Jika itu adalah direktori relatif terhadap file yang memerlukan (misalnya Anda ingin memuat semua file di direktori lib):
Anda juga dapat menambahkan semua direktori anak seperti iniDir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
jspooner
62
Mungkin lebih aman menggunakan File.join daripada membuat asumsi tentang garis miring / maju:Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
Chris
6
Ada juga require_relative
maasha
30
Jika Anda menggunakan> = ruby 2.0, Anda dapat menggunakan __dir__sebagai gantinya File.dirname(__FILE__).
Christian Bankester
3
@maasha Bagaimana Anda menggunakan require_relativesemua file dalam direktori?
Saya perlu memasukkan semua model ActiveRecord saya, permata require_all menemukan semua dependensi dan meminta mereka dengan sempurna. Terima kasih!
panupan
2
@panupan Ketahuilah bahwa require_allresolusi 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.
sheldonh
Tidak masuk akal untuk mengasapi aplikasi Anda dengan permata yang bisa Anda ganti dengan sederet kode. Ini meningkatkan waktu buka aplikasi Anda dan menginduksi lebih banyak bug dalam jangka panjang.
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").
Benarkah ini masalahnya? Dokumentasi mengatakan: Fitur tidak akan dimuat jika namanya sudah muncul dalam $ ". Nama file dikonversi ke jalur absolut, jadi" memerlukan 'a'; membutuhkan './a' "tidak akan memuat a.rb dua kali. ruby-doc.org/core/classes/Kernel.html#M001418
Derek
13
Pengujian saya menunjukkan hal yang sama dengan yang dikatakan Derek: require "foo.rb"; require "foo";akan dimuat foo.rbsekali saja.
Rene Saarsoo
@ PeteHodgson- Bisakah Anda mendukungnya?
Yarin
4
Tidak. Ruby requiretidak bingung dengan ada atau tidaknya .rbekstensi. 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).
Ini adalah kode yang indah. Saya suka bagaimana tidak ada blok yang terlihat.
Nate Symer
1
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )menghilangkan ketergantungan pada platform (seperti '/' atau '\'). Bekerja dengan baik. Terima kasih.
Ivan Black
30
Cara terbaik adalah menambahkan direktori ke path memuat dan kemudian requirenama 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 requiretelah melihat jalur yang dilewati sebelumnya. Misalnya, sesi irb sederhana ini menunjukkan bahwa Anda dapat secara keliru meminta dan memuat file yang sama dua kali.
Perhatikan bahwa dua baris pertama kembali yang trueberarti file yang sama dimuat dua kali. Saat jalur digunakan, bahkan jika jalur menunjuk ke lokasi yang sama, requiretidak 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 loadsebaiknya digunakan saja require. Gunakan beban dalam kasus ini, karena lebih baik mengekspresikan apa yang Anda coba capai. Sebagai contoh:
Karena Rails.rootini adalah Pathnamecontoh, Anda dapat melakukan ini di lingkungan Ruby apa pun, bukan hanya Rails (NB Rails.root.join('lib/ext/*.rb')sedikit lebih bagus)
DMKE
Terima kasih untuk rekomendasinya; Saya diedit untuk memasukkan komentar Anda.
Dan Kohn
Menggunakan garis miring (/) untuk sub-direktori di bawah Rails.root, untuk misalnya 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 }
Jignesh Gohel
@Jiggneshh Gohel Saya menghapus garis miring seperti yang Anda sarankan, terima kasih.
Dan Kohn
3
Saya beberapa tahun terlambat ke pesta, tapi saya agak suka solusi satu baris ini yang saya gunakan untuk mendapatkan kereta api untuk memasukkan semua yang ada di app / pekerja / masalah:
OKE, tetapi dalam contoh saya tidak. The '*' berubah arity menjadi 1. Ia berfungsi sebagai beberapa panggilan ke require_relative.
Aleksander
1
'*' Berubah menjadi 1 - Apa maksud Anda dengan itu? 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)
Jawaban:
Bagaimana tentang:
sumber
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):
Sunting: Berdasarkan komentar di bawah, versi yang diperbarui:
sumber
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
__dir__
sebagai gantinyaFile.dirname(__FILE__)
.require_relative
semua file dalam direktori?Coba permata require_all:
Ini memungkinkan Anda untuk:
sumber
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.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").
sumber
require "foo.rb"; require "foo";
akan dimuatfoo.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).atau sebagai alternatif, jika Anda ingin mengatur ruang lingkup file untuk dimuat ke folder tertentu:
penjelasan:
Dir.glob mengambil blok sebagai argumen.
metode (: wajib) akan mengembalikan metode yang diperlukan.
& metode (: wajib) akan mengonversi metode menjadi blok.
sumber
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 apakahrequire
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.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.
Jika Anda tidak peduli dengan file yang diminta lebih dari satu kali, atau niat Anda hanya untuk memuat konten file, mungkin
load
sebaiknya digunakan sajarequire
. Gunakan beban dalam kasus ini, karena lebih baik mengekspresikan apa yang Anda coba capai. Sebagai contoh:sumber
Alih-alih menyatukan jalur seperti dalam beberapa jawaban, saya menggunakan
File.expand_path
:Memperbarui:
Alih-alih menggunakan
File.dirname
Anda bisa melakukan hal berikut:Di mana
..
strip nama file__FILE__
.sumber
File.expand_path
Rails.root.join
jawaban juga berfungsi jika Anda berada di rel.Ini akan bekerja secara rekursif pada mesin lokal Anda dan remote (Suka Heroku) yang tidak menggunakan jalur relatif.
sumber
Di Rails, Anda dapat melakukan:
Pembaruan: Diperbaiki dengan saran dari @Jiggneshh Gohel untuk menghapus garis miring.
sumber
Rails.root
ini adalahPathname
contoh, Anda dapat melakukan ini di lingkungan Ruby apa pun, bukan hanya Rails (NBRails.root.join('lib/ext/*.rb')
sedikit lebih bagus)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 }
Saya beberapa tahun terlambat ke pesta, tapi saya agak suka solusi satu baris ini yang saya gunakan untuk mendapatkan kereta api untuk memasukkan semua yang ada di app / pekerja / masalah:
Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }
sumber
Dan bagaimana dengan
require_relative *Dir['relative path']
:?sumber
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)