Ruby'deki bir dizindeki tüm dosyaları istemenin en iyi yolu?


351

Ruby'deki bir dizindeki tüm dosyaları istemenin en iyi yolu nedir?


Dizin ile aynı ada sahip bir dosya oluşturabilir ve tüm dosyaları gerektirmesini sağlayabilirsiniz. RSpec bunu yapar.
pedromanoel

Yanıtlar:


462

Nasıl olur:

Dir["/path/to/directory/*.rb"].each {|file| require file }

18
Kazma göre .rb uzantısı isteğe bağlıdır. Teknik olarak anlamı değiştirir: "gerektirir 'foo.rb'" foo.rb gerektirir, "gerektirir 'foo'" foo.rb, foo.so veya foo.dll gerektirebilir.
Sam Stokes

28
Uzatmayı soymamak için ince bir şey var. Kod aramalarının başka bir kısmı 'foo' gerektiriyorsa, ruby ​​aynı dosyayı tekrar yükler ve bu da sahte hatalara neden olabilir. Bunu açıklayan ve uzantının nasıl şeritleneceğini gösteren kendi cevabımı ekledim.
Pete Hodgson

4
@Pete, bu hala doğru mu? Aşağıdaki Rene'nin yorumuna bakın.
Andres Riofrio

5
Bu açık olabilir, ancak .rb bırakmanın aynı zamanda dir içinde herhangi bir .rb olmayan dosya gerektireceğini de belirtmek gerekir.
user2398029

10
@ PeteHodgson'un önerisi yanlış. Ruby require, .rbuzantının varlığı veya yokluğu ile karıştırılmıyor . MRI 1.8.7-p374 üzerinde test edildi, 2.1.5 ve 2.2.0 test edildi. Bu kentsel efsane, "akıllı" otomatik yüklemenin eski sürümlerde tanımladığı davranışı sergilediği (ve yine de sergileyebileceği) Rails'ten geliyor.
sheldonh

345

Gerekli olan dosyaya göre bir dizinse (örn. Lib dizinindeki tüm dosyaları yüklemek istiyorsunuz):

Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }

Düzenleme: Aşağıdaki yorumlara dayanarak güncellenmiş bir sürüm:

Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }

14
Ayrıca bu gibi tüm alt dizinleri ekleyebilirsinizDir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
jspooner

62
İleri / geri eğik çizgiler hakkında varsayımlar yapmak yerine File.join'i kullanmak daha güvenlidir:Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
Chris

6
Ayrıca
requir_relative

30
> = Ruby 2.0 kullanıyorsanız, __dir__yerine = kullanabilirsiniz File.dirname(__FILE__).
Christian Bankester

3
@maasha require_relativeBir dizindeki tüm dosyaları istemek için nasıl kullanılır ?
David Moles

101

Requir_all gem deneyin:

  1. http://github.com/jarmo/require_all
  2. https://rubygems.org/gems/require_all

Basitçe:

require_all 'path/to/directory'

Tüm ActiveRecord modellerimi eklemem gerekiyordu, tüm bağımlılıkları anladım requir_all gem ve onları mükemmel gerekli. Teşekkürler!
panupan

2
@ panupan Sadece require_alldöngüsel bağımlılık çözümünün kaynak kodunuzdaki bir sorun etrafında çalıştığını unutmayın: bağımlılıklarını gerektirmeyen Ruby kaynak dosyalarınız var. Bu, kapıyı neşter yüklemesine kapatır ve sizi ya hep ya hiç yüklemeye adar. Bu küçük kütüphanelerde bir sorun değil, ama bilinçli olarak vermeniz gereken bir karar.
sheldonh

Uygulamanızı basitçe bir kod satırı ile değiştirebileceğiniz değerli taşlarla şişirmek mantıklı değildir. Bu, uygulamanızın yükleme süresini artırır ve uzun vadede daha fazla hataya neden olur.
Pere Joan Martorell

52
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file| 
  require File.basename(file, File.extname(file))
end

Uzantıyı kaldırmazsanız, aynı dosyayı iki kez isteyebilirsiniz (ruby, "foo" ve "foo.rb" öğelerinin aynı dosya olduğunu fark etmez). Aynı dosyaya iki kez ihtiyaç duyulması sahte uyarılara neden olabilir (örn. "Uyarı: zaten başlatılmış sabit").


11
Gerçekten böyle mi? Dokümantasyon şöyle diyor: Adı zaten $ "içinde görünüyorsa bir özellik yüklenmez. Dosya adı mutlak bir yola dönüştürülür, bu nedenle" a 'gerektirir'; İki kez a.rb yüklenmiyor './a'" gerektirir. ruby-doc.org/core/classes/Kernel.html#M001418
Derek

13
Testlerim Derek'in söylediği şeyi gösteriyor: sadece bir kez require "foo.rb"; require "foo";yüklenecek foo.rb.
Rene Saarsoo

@ PeteHodgson- Bunu yedekleyebilir misin?
Yarin

4
Hayır. Ruby'nin uzantının requirevarlığı veya yokluğu ile karıştırılmaması .rb. MRI 1.8.7-p374, 2.1.5 ve 2.2.0 üzerinde test edilmiştir. Bu kentsel efsane, "akıllı" otomatik yüklemenin eski sürümlerde açıklanan davranışı sergilediği (ve yine de sergileyebileceği) Rails'ten geliyor.
sheldonh

45
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))

veya alternatif olarak, dosyaları belirli klasörlere yüklenecek şekilde kapsamlandırmak istiyorsanız:

Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))

açıklama:

Dir.glob bir bloğu argüman olarak alır.

method (: requir) , method yöntemini döndürür.

& method (: requir) yöntemi bir bloğa dönüştürür.


2
Bu güzel bir kod. Görünür blokların nasıl olmadığını seviyorum.
Nate Symer

1
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )platforma olan bağımlılığı ortadan kaldırır ('/' veya '\' gibi). İyi çalışıyor. Teşekkürler.
Ivan Black

30

En iyi yol, dizini yükleme yoluna ve ardından requireher dosyanın taban adına eklemektir . Bunun nedeni, yanlışlıkla aynı dosyayı iki kez istemekten kaçınmak istemenizdir - genellikle amaçlanan davranış değildir. Bir dosyanın yüklenip yüklenmeyeceği, dosyaya daha requireönce aktarılan yolu görüp görmediğine bağlıdır . Örneğin, bu basit irb oturumu yanlışlıkla aynı dosyayı iki kez gerektirip yükleyebileceğinizi gösterir.

$ 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

İlk iki satırın trueaynı dosyanın her iki kez yüklendiği anlamına geldiğini unutmayın. Yollar kullanıldığında, yollar aynı konuma işaret etse bile require, dosyanın zaten gerekli olduğunu bilmez.

Bunun yerine, yükleme yoluna bir dizin ekliyoruz ve daha sonra içindeki her * .rb dosyasının taban adını gerektiriyoruz.

dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }

Dosyanın bir kereden fazla gerekli olmasını umursamıyorsanız veya amacınız yalnızca dosyanın içeriğini yüklemekse, loadbunun yerine belki de kullanılmalıdır require. Bu durumda yük kullanın, çünkü ne yapmaya çalıştığınızı daha iyi ifade eder. Örneğin:

Dir["/path/to/directory/*.rb"].each {|file| load file }

14

Bazı yanıtlardaki gibi yolları birleştirmek yerine şunu kullanıyorum File.expand_path:

Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
  require file
end

Güncelleme:

Kullanmak yerine File.dirnameaşağıdakileri yapabilirsiniz:

Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
  require file
end

Nerede ..dosya adını şeritler __FILE__.


Bu kesinlikle gitmek için bir yol gibi görünüyor, ve en güncel cevap, geri kalan her şeyi denedikten sonra +1 içinFile.expand_path
SuckerForMayhem

Bu cevabı kesinlikle kabul edilene tercih ederim. Rails.root.joinRaylardaysanız çeşitli cevaplar da işe yarar.
nzifnab

14
Dir[File.join(__dir__, "/app/**/*.rb")].each do |file|
  require file
end

Bu, yerel makinenizde ve göreli yolları kullanmayan bir uzaktan kumandada (Heroku gibi) tekrar tekrar çalışacaktır.


8

Rails'te şunları yapabilirsiniz:

Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }

Güncelleme: Eğik çizgileri kaldırmak için @Jiggneshh Gohel önerisiyle düzeltildi.


Yana Rails.rootbir olan Pathnameörnek, herhangi Yakut ortamında bunu yapabilirsiniz, sadece (NB Raylar Rails.root.join('lib/ext/*.rb')biraz daha hoş okur)
DMKE

Tavsiye için teşekkürler; Yorumunuzu eklemek için düzenledim.
Dan Kohn

Örneğin Rails.root altındaki alt dizinler için eğik çizgi (/) kullanmak Rails.root.join('/lib')doğru yol oluşturmaz. Bunu doğru çalışması için buldum:Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Jignesh Gohel

@Jiggneshh Gohel İstediğiniz gibi eğik çizgileri çıkardım, teşekkürler.
Dan Kohn

3

Partiye birkaç yıl geç kaldım, ancak uygulama / işçiler / endişelere her şeyi dahil etmek için raylar alırdım bu tek satırlık çözümü beğendim:

Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }


-2

Peki ya: require_relative *Dir['relative path']?



Tamam, ama benim örneğimde öyle değil. '*', 1 değerini değiştirir. Requ_re_relative için çoklu çağrı olarak çalışır.
Aleksander

1
'*', İkiliği 1 olarak değiştirir - Bununla ne demek istiyorsun? require_relative *Dir['*.rb']sadece bir ruby-script varsa çalışın. Birden yakut komut bulunursa Ama eğer olsunrequire_relative': wrong number of arguments (4 for 1) (ArgumentError)
knut
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.