루비의 디렉토리에서 모든 파일을 요구하는 가장 좋은 방법은 무엇입니까?


351

루비의 디렉토리에서 모든 파일을 요구하는 가장 좋은 방법은 무엇입니까?


동일한 디렉토리 이름으로 파일을 작성하고 모든 파일을 요구하도록 할 수 있습니다. RSpec이이를 수행합니다.
pedromanoel 1

답변:


462

어때요 :

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

18
Pickaxe에 따르면 .rb 확장자는 선택 사항입니다. 기술적으로 의미를 변경합니다. " 'foo.rb'필요"에는 foo.rb가 필요하지만 " 'requir'필요"에는 foo.rb, foo.so 또는 foo.dll이 필요할 수 있습니다.
Sam Stokes

28
확장을 제거하지 않는 미묘한 차이가 있습니다. 코드 호출의 다른 부분에 'foo'가 필요한 경우 ruby는 동일한 파일을 다시로드하여 잘못된 오류를 일으킬 수 있습니다. 나는 그것을 설명하고 확장을 제거하는 방법을 보여주는 내 자신의 대답을 추가했습니다.
Pete Hodgson

4
@Pete, 이것이 사실입니까? 아래의 Rene의 의견을 참조하십시오 .
Andres Riofrio

5
이것은 명백 할 수도 있지만 .rb를 삭제하면 dir에 .rb 파일이 아닌 파일이 필요하다는 점에 주목할 필요가 있습니다.
user2398029

10
@PeteHodgson의 제안이 정확하지 않습니다. 루비 require.rb확장의 유무에 의해 혼동되지 않습니다 . MRI 1.8.7-p374, 2.1.5 및 2.2.0에서 테스트되었습니다. 이 도시의 전설은 Rails에서 나 왔으며, "영리한"자동 로딩은 이전 버전에서 묘사 한 행동을 보여주었습니다.
sheldonh

345

그것이 필요한 파일과 관련된 디렉토리 인 경우 (예를 들어, lib 디렉토리에 모든 파일을로드하려는 경우) :

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

편집 : 아래 설명에 따라 업데이트 된 버전 :

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

14
당신은 또한이 같은 모든 하위 디렉토리를 추가 할 수 있습니다Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|file| require file }
jspooner

62
슬래시 (/)를 가정하는 것보다 File.join을 사용하는 것이 더 안전 할 것입니다.Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|file| require file }
Chris

6
require_relative도있다
maasha는

30
> = ruby ​​2.0을 사용 __dir__하는 경우 대신 대신 사용할 수 있습니다 File.dirname(__FILE__).
Christian Bankester 14

3
@maasha require_relative디렉토리의 모든 파일을 요구 하는 데 어떻게 사용 합니까?
David Moles

101

require_all gem을 사용해보십시오 :

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

간단하게 할 수 있습니다 :

require_all 'path/to/directory'

필자는 모든 ActiveRecord 모델을 포함해야했고 require_all gem은 모든 종속성을 파악하여 완벽하게 요구했습니다. 감사!
panupan

2
@panupan require_all's 주기적 종속성 해결은 소스 코드의 문제를 해결하는 데 도움이됩니다. 종속성이 필요없는 Ruby 소스 파일이 있습니다. 이렇게하면 메스 로딩시 도어가 닫히고 전혀로드되지 않거나 전혀로드되지 않습니다. 소규모 도서관에서는 문제가되지 않지만 의식적으로 결정해야합니다.
sheldonh

단순히 코드 줄로 바꿀 수있는 보석으로 앱을 부 풀리는 것은 의미가 없습니다. 이렇게하면 앱의로드 시간이 늘어나고 장기적으로 더 많은 버그가 발생합니다.
Pere Joan Martorell

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

확장명을 제거하지 않으면 동일한 파일을 두 번 요구하게됩니다 (루비는 "foo"와 "foo.rb"가 같은 파일이라는 것을 인식하지 못합니다). 동일한 파일을 두 번 요구하면 가짜 경고 (예 : "경고 : 이미 초기화 된 상수")가 발생할 수 있습니다.


11
이것이 사실입니까? 설명서에는 다음과 같은 내용이 나와 있습니다. 기능 이름이 이미 $ "로 표시되면 기능이로드되지 않습니다. 파일 이름이 절대 경로로 변환되므로"require 'a'; './a'필요 '는 a.rb를 두 번로드하지 않습니다. ruby-doc.org/core/classes/Kernel.html#M001418
Derek

13
내 테스트는 데릭이 말한 것과 동일합니다 . 한 번만 require "foo.rb"; require "foo";로드됩니다 foo.rb.
Rene Saarsoo

@ PeteHodgson- 이것을 백업 할 수 있습니까?
Yarin

4
require아닙니다. 루비 는 .rb확장의 유무에 의해 혼동되지 않습니다 . MRI 1.8.7-p374, 2.1.5 및 2.2.0에서 테스트되었습니다. 이 도시의 전설은 Rails에서 나 왔으며, "영리한"자동 로딩은 이전 버전에서 설명 된 동작을 보여 주었으며 여전히이를 보여줄 수 있습니다.
sheldonh

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

또는 특정 폴더로로드 할 파일의 범위를 지정하려는 경우 :

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

설명:

Dir.glob 는 블록을 인수로 사용합니다.

method (: require) 는 require 메소드를 반환합니다.

& method (: require)는 메소드를 블록으로 변환합니다.


2
이것은 아름다운 코드입니다. 나는 눈에 보이는 블록이없는 것을 좋아합니다.
Nate Symer

1
Dir.glob( File.join( File.dirname(__FILE__), '{lib,addons}', 'subfolder', '**', '*.rb' ), &method(:require) )플랫폼에 대한 의존성을 제거합니다 (예 : '/'또는 '\'). 잘 작동합니다. 감사.
Ivan Black

30

가장 좋은 방법은 디렉토리를로드 경로에 추가 한 다음 require각 파일의 기본 이름 을 추가하는 것 입니다. 의도하지 않은 동일한 파일을 실수로 두 번 요구하지 않기를 원하기 때문입니다. 파일로드 여부 require는 이전에 전달 된 경로를 보았는지 여부에 따라 다릅니다 . 예를 들어,이 간단한 irb 세션은 실수로 같은 파일을 두 번 요구하고로드 할 수 있음을 보여줍니다.

$ 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

처음 두 줄 true은 같은 파일이 두 번로드되었다는 것을 의미합니다. 경로가 사용되는 경우 경로가 동일한 위치를 가리켜도require 파일이 이미 필요한지 알 수 없습니다.

대신로드 경로에 디렉토리를 추가 한 다음 각 * .rb 파일의 기본 이름이 필요합니다.

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

파일이 두 번 이상 필요한 것에 신경 쓰지 않거나 파일의 내용을로드하려는 의도라면 load대신 대신 사용해야합니다 require. 이 경우로드를 사용하십시오. 달성하려는 것을 더 잘 표현하기 때문입니다. 예를 들면 다음과 같습니다.

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

14

일부 답변과 같은 경로를 연결하는 대신 다음을 사용합니다 File.expand_path.

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

최신 정보:

사용하는 대신 File.dirname다음을 수행 할 수 있습니다.

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

어디 ..의 파일 이름을 제거합니다 __FILE__.


이것은 확실히 갈 길을 것, 그리고 모든 나머지 하나를 시도 후 날짜 대답 가장,File.expand_path
SuckerForMayhem

나는이 대답을 받아 들인 대답보다 선호합니다. Rails.root.join당신이 레일에 있다면 다양한 답변도 작동합니다.
nzifnab 2013 년

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

이것은 로컬 컴퓨터와 상대 경로를 사용하지 않는 원격 장치 (Heroku와 유사)에서 재귀 적으로 작동합니다.


8

Rails에서는 다음을 수행 할 수 있습니다.

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

업데이트 : @Jiggneshh Gohel의 제안으로 슬래시를 제거하도록 수정되었습니다.


이후 Rails.rootA는 Pathname인스턴스가, 당신이 어떤 루비 환경에서이 작업을 수행 할 수 있습니다뿐만 아니라 (NB는 레일 Rails.root.join('lib/ext/*.rb')조금 더 좋은를 읽고)
DMKE

추천 해 주셔서 감사합니다. 귀하의 의견을 포함하도록 편집했습니다.
Dan Kohn

예를 들어 Rails.root 아래의 하위 디렉토리에 슬래시 (/)를 사용하면 Rails.root.join('/lib')올바른 경로가 생성되지 않습니다. 나는 이것이 올바르게 작동하는 것을 발견했다 :Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Jignesh Gohel

@ Jiggneshh Gohel 제안한대로 슬래시를 제거했습니다. 감사합니다.
Dan Kohn

3

나는 파티에 몇 년 늦었지만, 나는 한 줄 솔루션과 비슷합니다.

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


-2

그리고 require_relative *Dir['relative path']어때요?


1
친척이 여러 파일을 가져 가지 않음 : ruby-doc.org/core-2.1.2/Kernel.html#method-i-require_relative
fabriciofreitag

좋아,하지만 내 예에서는 그렇지 않습니다. '*'는 arity를 ​​1로 변경합니다. require_relative에 대한 다중 호출로 작동합니다.
Aleksander

1
'*'는 arity를 ​​1로 바꿉니다. 무슨 의미입니까? require_relative *Dir['*.rb']루비 스크립트가 하나만 있으면 작동합니다. 그러나 여러 루비 스크립트가 발견되면require_relative': wrong number of arguments (4 for 1) (ArgumentError)
knut
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.