Development Tip

로드는 Ruby의 require와 어떻게 다릅니 까?

yourdevel 2020. 10. 16. 08:12
반응형

로드는 Ruby의 require와 어떻게 다릅니 까?


Ruby on Rails 애플리케이션 load사이에 큰 차이점이 require있습니까? 아니면 둘 다 동일한 기능을 가지고 있습니까?


require정의 된 모든 검색 경로에서 라이브러리를 검색하고 입력 한 파일 이름에 .rb 또는 .so를 추가합니다. 또한 라이브러리가 한 번만 포함되도록합니다. 따라서 응용 프로그램에 라이브러리 A와 B가 필요하고 라이브러리 B에 라이브러리 A가 필요한 경우 A도 한 번만로드됩니다.

으로 load당신은 라이브러리의 전체 이름을 추가 할 필요가 그것을 당신이 호출 할 때마다로드되는 load- 이미 메모리에있는 경우에도 마찬가지입니다.


또 다른 차이점 Kernel#requireKernel#loadKernel#load익명 빈 모듈에로드 된 코드를 포장 할 수있는 옵션은 2 개의 인자를 가지고.

불행히도 그다지 유용하지 않습니다. 첫째, load글로벌 네임 스페이스에 액세스하기 만하면 ed 코드가 모듈 에서 쉽게 빠져 나올 수 있습니다 class ::String; def foo; end end. 즉, 여전히 . 둘째, load코드를 래핑 한 모듈을 반환하지 않으므로 기본적으로 ObjectSpace::each_object(Module)손으로 빼내야합니다.


저는 Rails 애플리케이션을 실행하고 있었고 Gemfile에서 "require : false"옵션을 사용하여 만든 특정 사용자 지정 gem을 가지고있었습니다. 이제 Rails 서버 또는 Rails 콘솔을로드 할 때 이니셜 라이저에서 gem을 요구할 수 있었고 gem이로드되었습니다. 그러나 rspec 및 capybara로 사양 기능 테스트를 실행했을 때로드 오류가 발생했습니다. 그리고 테스트를 실행할 때 $ LOAD_PATH에서 Gem을 찾을 수없는 이유가 완전히 당황했습니다.

그래서로드, 요구, rubygems 및 번 들러가 상호 작용하는 모든 다른 방법을 검토했습니다. 그리고 다음은 내 특정 문제에 대한 해결책을 찾는 데 도움이 된 내 결과 요약입니다.

하중

1) 루비 파일의 절대 경로를 전달할 수 있으며 해당 파일의 코드를 실행합니다.

load('/Users/myuser/foo.rb')

2)로드 할 상대 경로를 전달할 수 있습니다. 파일과 동일한 디렉토리에있는 경우 다음을 찾습니다.

> load('./foo.rb')
foo.rb loaded!
=> true

그러나 load ()를 사용하여 다른 디렉토리에서 파일을로드하려고하면 현재 작업 디렉토리 (예 : ./)에 기반한 상대 경로로 파일을 찾지 못합니다.

> load('./foo.rb')
LoadError: cannot load such file -- foo.rb

3) 위에 표시된 것처럼 load는 항상 true를 반환합니다 (파일을로드 할 수없는 경우 LoadError).

4) 전역 변수, 클래스, 상수 및 메서드는 모두 가져 오지만 로컬 변수는 가져 오지 않습니다.

5) 동일한 파일에서 load를 두 번 호출하면 해당 파일의 코드가 두 번 실행됩니다. 지정된 파일이 상수를 정의하면 해당 상수를 두 번 정의하여 경고를 생성합니다.

6) $ LOAD_PATH는 절대 경로의 배열입니다. 파일 이름 만로드하면 $ LOAD_PATH를 반복하고 각 디렉토리에서 파일을 검색합니다.

> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
 => true

요구하다

1) 동일한 파일에서 require를 두 번 호출하면 한 번만 실행됩니다. 또한 상대 경로로 한 번, 절대 경로로 한 번 참조하면 동일한 파일을 두 번로드하지 않을만큼 똑똑합니다.

2) require는 파일이 실행되면 true를 반환하고 그렇지 않으면 false를 반환합니다.

3) require는 전역 변수 $ LOADED_FEATURES에 이미로드 된 파일을 추적합니다.

4) 파일 확장자를 포함 할 필요가 없습니다.

require 'foo'

5) require는 foo.rb뿐만 아니라 foo.so, foo.o 또는 foo.dll과 같은 동적 라이브러리 파일도 찾습니다. 이것이 루비에서 C 코드를 호출하는 방법입니다.

6) require는 현재 디렉토리가 기본적으로 $ LOAD_PATH에 없기 때문에 현재 디렉토리를 확인하지 않습니다.

7) require_relative는 프로세스의 작업 디렉토리가 아닌 현재 파일에 상대적인 경로를 취합니다.

Rubygems

1) Rubygems는 gems라는 Ruby 라이브러리 설치를 쉽게 관리 할 수 ​​있도록 설계된 패키지 관리자입니다.

2) 일부 메타 데이터와 함께 코드에서 가져올 수있는 루비 파일 및 / 또는 동적 라이브러리 파일이 포함 된 zip 파일로 콘텐츠를 패키징합니다.

3) Rubygems는 기본 require 메소드를 자체 버전으로 대체합니다. 이 버전은 $ LOAD_PATH의 디렉토리 외에 설치된 gem을 살펴 봅니다. Rubygems가 gem에서 파일을 찾으면 해당 gem을 $ LOAD_PATH에 추가합니다.

4) gem install 명령은 gem의 모든 종속성을 파악하여 설치합니다. 사실, gem 자체를 설치하기 전에 모든 gem의 의존성을 설치합니다.

번 들러

1) Bundler를 사용하면 프로젝트에 필요한 모든 gem을 지정하고 선택적으로 해당 gem의 버전을 지정할 수 있습니다. 그런 다음 bundle 명령은 모든 gem과 해당 종속성을 설치합니다.

2) Gemfile이라는 파일에서 필요한 gem을 지정합니다.

3) bundle 명령은 또한 나열된 특정 버전에서 Gemfile.lock에 나열된 모든 gem을 설치합니다.

4) Putting bundle exec before a command, e.g. bundle exec rspec, ensures that require will load the version of a gem specified in your Gemfile.lock.

Rails and Bundler

1) In config/boot.rb, require 'bundler/setup' is run. Bundler makes sure that Ruby can find all of the gems in the Gemfile (and all of their dependencies). require 'bundler/setup' will automatically discover your Gemfile, and make all of the gems in your Gemfile available to Ruby (in technical terms, it puts the gems “on the load path”). You can think of it as an adding some extra powers to require 'rubygems'.

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])

2) Now that your code is available to Ruby, you can require the gems that you need. For instance, you can require 'sinatra'. If you have a lot of dependencies, you might want to say “require all of the gems in my Gemfile”. To do this, put the following code immediately following require 'bundler/setup':

Bundler.require(:default)

3) By default, calling Bundler.require will require each gem in your Gemfile. If the line in the Gemfile says gem 'foo', :require => false then it will make sure foo is installed, but it won’t call require. You’ll have to call require('foo') if you want to use the gem.

So given this breadth of knowledge, I returned to the issue of my test and realized I had to explicitly require the gem in rails_helper.rb, since Bundler.setup added it to $LOAD_PATH but require: false precluded Bundler.require from requiring it explicitly. And then the issue was resolved.

참고URL : https://stackoverflow.com/questions/3170638/how-does-load-differ-from-require-in-ruby

반응형