Ruby에서 종속성을 관리하려면 일반적으로 프로젝트가 의존하는 Ruby 및 gem 버전을 지정해야 합니다. Ruby로 작업한 경험에 따르면 종속성을 디버깅하는 것이 가장 큰 문제 중 하나였습니다. 많은 것들이 "그냥 작동"하기 때문에 실패는 일반적이지 않습니다. 그러나 일이 잘못되면 일반적으로 디버그하고 수정하기가 불필요하게 어렵습니다. 이 기사에서는 Ruby에서 종속성 관리와 관련된 부분을 배치합니다. 이렇게 하면 이러한 이상한 문제가 발생할 때 디버깅하는 데 도움이 됩니다.
루비 코드 로딩
기본적으로 Ruby 언어는 다른 곳에 정의된 코드를 로드하기 위한 두 가지 주요 방법을 제공합니다. load
&require
.
load 'json.rb'
require 'json.rb'
require_relative 'json.rb'
두 로드 방법 모두 절대 및 상대 경로를 인수로 허용합니다. 그러나 두 가지 차별화 요소가 있습니다.
load
에 대한 다중 호출require
를 여러 번 호출하면 파일이 다시 실행됩니다. 파일을 다시 실행하지 않습니다. 대신false
를 반환합니다. .load
호출 절대 및 상대 경로로만 확인됩니다.require
호출$LOAD_PATH
확인 경로가 절대 경로로 확인되지 않는 경우.
세 번째 변형은 require_relative
입니다. , 상대 경로를 사용하여 Ruby 프로세스의 작업 디렉토리가 아닌 현재 파일의 위치에 상대적인 코드를 요구합니다.
Rbenv
버전 관리자는 인터프리터(이 경우 Ruby) 버전을 관리하고 쉽게 전환하고 프로젝트의 각 gem을 찾을 위치를 지정하는 데 사용되는 도구입니다. 버전 관리자는 주로 언어에 구애받지 않는 도구이며 다양한 언어에는 Node.js의 경우 Nvm, n, Python의 경우 pyenv, Ruby의 경우 Rbenv, rvm 및 chruby와 같이 각각의 구현이 있습니다. 이제 rbenv
를 살펴보겠습니다. 한 번 돌려볼까요?
루비 버전 설치
rbenv install
명령을 사용합니다. 모든 버전의 Ruby를 설치하려면:
# Install ruby 2.6.1
$ rbenv install 2.6.1
Downloading openssl-1.1.1i.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
Installing openssl-1.1.1i...
Installed openssl-1.1.1i to /home/directory/.rbenv/versions/2.6.1
Downloading ruby-2.6.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.bz2
Installing ruby-2.6.1...
ruby-build: using readline from homebrew
Installed ruby-2.6.1 to /home/directory/.rbenv/versions/2.6.1
# Check Installation
$ rbenv versions # Shows all versions installed.
system
2.6.1
# Lookup versions available for installation
$ rbenv install -L
1.8.5-p52
1.8.5-p113
1.8.5-p114
...
2.7.0-rc1
2.7.0-rc2
2.7.0
...
truffleruby+graalvm-20.1.0
truffleruby+graalvm-20.2.0
truffleruby+graalvm-20.3.0
# The full list above amounts to about 500 versions, scrolling through the entire list is a lot.
# The command below is an easy shortcut to find your specific version with fzf.
$ rbenv install `rbenv install -L | fzf`
버전 간 전환
Ruby 버전 간에 전환하는 방법을 식별하는 방법에는 여러 가지가 있습니다. 항상 rbenv
다음을 수행합니다.
RBENV_VERSION
확인 ..ruby-version
검색 루트 디렉토리에 도달할 때까지 스크립트의 디렉토리와 그 상위 파일에 있습니다..ruby-version
검색$PWD
의 파일 루트 디렉토리에 도달할 때까지 상위 디렉토리에 있습니다.- 전역 파일 사용
~/.rbenv/version
.
우선 순위는 위에서 아래로 이동합니다. ~/.rbenv/version
최종 대체이며 전역 버전으로 처리됩니다. 아래 참조:
# Inside First Project Root
# Select ruby version for project
$ touch .ruby-version && echo "2.7.1" >> .ruby-version
# Verify selected version
$ ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin20] # Result
$ rbenv version
2.7.1 (set by /path/to/current/directory/.ruby-version) # Result
# Change selected version
$ : >> .ruby-version && echo "2.6.1" >> .ruby-version
# Verify selection change
$ ruby --version
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin20] # Result
$ rbenv version
2.6.1 (set by /path/to/current/directory/.ruby-version)
# Change selection with RBENV_VERSION while .ruby-version is present
$ export RBENV_VERSION=2.5.1
# Verify selection change
# .ruby-version is ignored.
$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin20] # Result
$ rbenv version
2.5.1 (set by RBENV_VERSION environment variable) # Result
# Change to a version that is not installed & remove RBENV_VERSION
$ unset RBENV_VERSION & : >> .ruby-version && echo "2.4.1" >> .ruby-version
# Verify selection change
$ ruby --version
rbenv: version `2.4.1' is not installed (set by full/path/to/current/directory/.ruby-version) # Result
심 및 재해싱
rbenv
를 디버그할 수 있으려면 이 두 가지 개념을 제대로 이해해야 합니다. 효과적으로.
Shim은 PATH
에 존재하는 가벼운 bash 스크립트입니다. 명령을 가로채 실행을 위해 적절한 버전으로 라우팅합니다. 높은 수준에서 모든 명령(예:rspec
)는 rbenv exec rspec
으로 변환됩니다. . 자세한 내용은 아래를 참조하세요.
먼저 rbenv
모든 명령에 대한 shim을 만듭니다(rspec
, bundle
등) 설치된 모든 Ruby 버전에서 버전에 관계없이 CLI 호출을 가로챕니다. 이 shim은 ~/.rbenv/shims
에서 찾을 수 있습니다. . 모든 shim에는 아래와 같이 동일한 bash 스크립트가 포함되어 있습니다.
#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x
program="${0##*/}"
if [ "$program" = "ruby" ]; then
for arg; do
case "$arg" in
-e* | -- ) break ;;
*/* )
if [ -f "$arg" ]; then
export RBENV_DIR="${arg%/*}"
break
fi
;;
esac
done
fi
export RBENV_ROOT="/home/directory/.rbenv"
exec "/usr/local/Cellar/rbenv/1.1.2/libexec/rbenv" exec "$program" "$@"
다음으로 위의 스크립트는 대략 다음과 같이 번역됩니다.
- 프로그램 이름이
ruby
인 경우 인수-e
사용 ,rbenv exec ruby <args>
로 번역
- 프로그램 이름이
ruby
인 경우 스크립트 경로,RBENV_DIR
설정 스크립트의 디렉토리로 이동합니다. 이렇게 하면rbenv
가 활성화됩니다..ruby-version
검색$PWD
앞의 스크립트 디렉토리 ..ruby-version
인 경우rbenv
두 위치에 모두 지정됩니다. 스크립트의 디렉토리를 선택합니다.
- 프로그램 이름이 Ruby가 아닌 경우
rbenv exec <program-name> <args>
로 번역 .
마지막으로 rbenv exec <command-name> <args>
RBENV_VERSION
을 확인하여 명령을 전달할 올바른 버전을 식별합니다. 환경 변수. RBENV_VERSION
을(를) 기억하십시오. 위에서 정의한 알고리즘에 의해 설정됩니다.
PATH
의 심 앞에 붙여야 합니다. 이렇게 하면 Ruby 실행 파일에 대한 첫 번째 접촉 지점이 되고 적절하게 가로챌 수 있습니다. PATH
를 이해하는 가장 좋은 방법 shim이 제대로 가로채는지 여부를 설정하고 확인하는 방법은 다음과 같습니다.
$ which -a bundle
/path/to/home/.rbenv/shims/bundle
/usr/bin/bundle
which -a bundle
:이것은 PATH
를 순진하게 살펴봅니다. bundle
가 있는 위치를 찾은 순서대로 인쇄합니다. 찾을수있다. ~/.rbenv/shims
에서 무엇인가 앞에 인쇄된 경우 , 심이 제대로 설정되지 않았음을 의미합니다. rbenv which bundle
명령이 rbenv
컨텍스트에서 작동하기 때문에 이를 공개하지 않습니다. PATH
를 검색하지 않음 .
Rehashing은 shim을 만드는 과정입니다. rspec
과 같이 실행 파일을 제공하는 Ruby gem을 새로 설치할 때 , rbenv rehash
를 실행해야 합니다. shim을 생성하여 rspec
에 대한 후속 호출이 rbenv
가 가로챌 수 있습니다. 적절한 Ruby 버전으로 전달됩니다.
루비젬
다음은 RubyGems입니다. Ruby 공식 사이트에서 다운로드할 수 있습니다. RubyGems는 라이브러리 생성, 공유 및 설치를 용이하게 하도록 설계된 Ruby 패키징 시스템입니다. 어떤 면에서는 apt-get과 비슷하지만 Ruby 소프트웨어를 대상으로 하는 배포 패키징 시스템입니다. RubyGems는 보석을 공유하는 사실상의 방법입니다. 일반적으로 ~/.rbenv/versions/{version-number}/lib/ruby/gems/{minor-version}/
에 설치됩니다. 사용되는 버전 관리자에 따라 또는 그 변형입니다. Ruby의 기본 필수 메소드 Kernel.require
Gems 설치 디렉토리에서 gem을 로드하는 메커니즘을 제공하지 않습니다. RubyGems 원숭이 패치 Kernel.require
- 먼저
$LOAD_PATH
에서 gem을 검색합니다. . - 찾을 수 없으면
GEMS INSTALLATION DIRECTORY
에서 보석을 검색하십시오. .- 찾으면
$LOAD_PATH
에 경로 추가 .
- 찾으면
이것은 Ruby가 버전 1.9부터 기본적으로 RubyGems와 함께 제공되기 때문에 "기본적으로" 작동합니다. 이전 Ruby 버전에서는 RubyGems를 수동으로 설치해야 했습니다. 이것은 기본적으로 작동하지만 디버깅할 때 이 차이점을 아는 것도 중요합니다.
보석은 특정 문제를 해결하는 데 사용되는 관련 코드 묶음입니다. 다음과 같이 gem을 설치하고 gem 환경에 대한 정보를 얻으세요.
$ gem install gemname
$ gem env
RubyGems Environment:
- RUBYGEMS VERSION: 3.1.2
- RUBY VERSION: 2.7.1 (2020-03-31 patchlevel 83) [x86_64-darwin20]
- INSTALLATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
- USER INSTALLATION DIRECTORY: /path/to/home/.gem/ruby/2.7.0
- RUBY EXECUTABLE: /path/to/home/.rbenv/versions/2.7.1/bin/ruby
- GIT EXECUTABLE: /usr/bin/git
- EXECUTABLE DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/bin
- SPEC CACHE DIRECTORY: /path/to/home/.gem/specs
- SYSTEM CONFIGURATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/etc
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-20
- GEM PATHS:
- /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
- /path/to/home/.gem/ruby/2.7.0
- GEM CONFIGURATION:
...
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
- /path/to/home/.rbenv/versions/2.7.1/bin
RubyGems는 이 문제를 어떻게 해결합니까? 원숭이는 Kernel
을 패치합니다. 자체 require
가 있는 require 시스템 방법. 이 제자리를 사용하면 require honeybadger
할 때 호출되면 gem 폴더에서 honeybadger.rb
를 검색합니다. 발견하면 보석을 활성화합니다.
예를 들어, require 'honeybadger'
다음과 유사한 결과를 생성합니다.
spec = Gem::Specification.find_by_path('honeybadger')
spec.activate
gem을 활성화한다는 것은 단순히 $LOAD_PATH
에 넣는 것을 의미합니다. . RubyGems는 또한 gem 자체를 다운로드하기 전에 gem의 모든 종속성을 다운로드하는 데 도움이 됩니다.
또한 Rubygems에는 gem open <gem-name>
으로 연결된 gem의 디렉토리를 열 수 있는 멋진 기능이 있습니다.; 예를 들어,
이를 통해 앱이 참조하는 gem의 특정 버전을 쉽게 찾고 추적할 수 있습니다.
번들러
이 계층에서 Bundler는 모든 프로젝트 종속성을 쉽게 지정하고 선택적으로 각각에 대한 버전을 지정하는 데 도움이 됩니다. 그런 다음 gem을 해결하고 gem과 해당 종속성을 설치합니다. 실제 애플리케이션 사전 번들러를 구축하는 데는 다음과 같은 수많은 과제가 수반되었습니다.
- 저희 애플리케이션은 수많은 종속성을 가지고 있으며 이러한 종속성은 다양한 기타 종속성과 각각의 버전을 가지고 있습니다. 하나의 gem의 잘못된 버전을 설치하면 앱이 쉽게 중단되며 이 문제를 수정하는 데 많은 눈물이 필요했습니다.
- 또한 종속성 중 2개는 동일한 3단계 종속성을 참조할 수 있습니다. 호환성을 찾는 것이 문제였고 문제가 있었다면 문제였습니다.
- 같은 시스템에 여러 애플리케이션이 있고 다양한 종속성이 있는 경우 애플리케이션은 시스템에 설치된 모든 gem에 액세스할 수 있습니다. 이는 최소 권한 원칙에 위배되고 애플리케이션이 시스템에 설치된 모든 gem에 노출됩니다. 악성인지 여부.
Bundler는 세 가지 문제를 모두 해결하고 다음을 수행하여 앱 종속성을 관리하는 올바른 방법을 제공합니다.
번들러는 종속성을 해결하고 잠금 파일을 생성합니다.
# Gemfile
gem 'httparty'
bundle
을 실행하면 또는 bundle install
, 잠금 파일을 생성합니다:
GEM
specs:
httparty (0.18.1)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2020.1104)
multi_xml (0.6.0)
PLATFORMS
ruby
DEPENDENCIES
httparty
BUNDLED WITH
2.1.4
위에서 번들러는 httparty
버전을 생성합니다. Gemfile.lock.
의 자체 종속성뿐만 아니라 설치해야 합니다. 이 파일은 앱 종속성의 청사진이며 버전 제어에 체크인해야 합니다. 이를 통해 프로젝트 종속성이 환경(개발, 스테이징 또는 프로덕션) 전반에 걸쳐 일관되게 유지됩니다.
번들러는 종속성 간의 호환성을 해결합니다.
httparty
에 대한 종속성을 해결합니다. 종속성에 적합한 버전을 찾고 지정합니다. Bundler는 또한 gem 간의 종속성을 해결하려고 시도합니다. 예를 들어,
# Gemfile
gem 'httparty' # That relies on gem 'mime-types', '>= 3.0.1, < 4.0.1'
gem 'rest-client' # That relies on gem 'mime-types', '>= 2.0.1, < 3.0'
위의 예는 임의적이며 다음과 같은 오류가 발생합니다.
Bundler could not find compatible versions for gem "mime-types":
In Gemfile:
httparty was resolved to 0.18.1, which depends on
mime-types ('>= 3.0.1, < 4.0.1')
rest-client was resolved to 2.0.4, which depends on
mime-types ('>= 2.0.1, < 3.0')
이는 두 gem에 호환되지 않고 자동으로 해결할 수 없는 종속성이 있기 때문입니다.
번들러는 설치되었지만 Gemfile
에 지정되지 않은 gem에 대한 액세스를 제한합니다.
다음과 같은 샘플 gemfile에서
# Gemfile
gem 'httparty'
# irb
require 'rest-client'
# raises
LoadError (cannot load such file -- rest-client)
Gemfile
에 지정된 종속성만 확인합니다. 우리 프로젝트에 필요할 수 있습니다.
번들 실행
rspec
을 실행할 때 프로젝트 디렉토리에서 Gemfile
에 지정된 것과 다른 버전을 실행할 가능성이 있습니다. . 이는 Gemfile
에 지정된 버전과 비교하여 가장 최신 버전이 실행되도록 선택되기 때문입니다. . bundle exec rspec
rspec
보장 해당 프로젝트의 컨텍스트에서 실행됩니다(즉, Gemfile에 지정된 gem).
binstub 번들
종종 ./bin/rails
와 같은 명령을 실행하는 기사를 읽습니다.; 이 명령은 bundle exec rails
와 유사합니다. . Binstub은 bundle exec
사용을 쉽게 해주는 Ruby 실행 파일을 둘러싼 래퍼입니다. .
binstub 실행을 생성하려면 bundle binstubs gem-name
을 사용하세요. . 이것은 ./bin
에 binstub를 생성합니다. 폴더이지만 --path
로 구성할 수 있습니다. 설정된 경우 디렉토리.
참조
자세히 알아보려면 다음 참조를 확인하십시오.
- 보석은 어떻게 작동합니까?
- 르벤브
- RubyGems
- 번들러