Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

보석은 어떻게 작동합니까?

대부분 Ruby Just Work의 보석입니다. 하지만 Ruby 매직에는 큰 문제가 있습니다. 일이 잘못되면 원인을 찾기가 어렵습니다.

보석에 문제가 자주 발생하지 않습니다. 그러나 그렇게 할 때 Google은 놀라울 정도로 도움이 되지 않습니다. 오류 메시지는 일반적이므로 다양한 원인 중 하나가 있을 수 있습니다. 젬이 실제로 Ruby에서 작동하는 방식을 이해하지 못한다면 이러한 문제를 스스로 디버깅하는 데 어려움을 겪을 것입니다.

보석이 보일 수 있습니다. 마법 같은. 하지만 조금만 조사하면 이해하기가 매우 쉽습니다.

gem install의 기능 할래?

Ruby gem은 약간의 추가 데이터로 압축된 일부 코드입니다. gem unpack으로 gem 내부의 코드를 볼 수 있습니다. :

~/Source/playground jweiss$ gem unpack resque_unit
Fetching: resque_unit-0.4.8.gem (100%)
Unpacked gem: '/Users/jweiss/Source/playground/resque_unit-0.4.8'
~/Source/playground jweiss$ cd resque_unit-0.4.8 
~/Source/playground/resque_unit-0.4.8 jweiss$ find .
.
./lib
./lib/resque_unit
./lib/resque_unit/assertions.rb
./lib/resque_unit/errors.rb
./lib/resque_unit/helpers.rb
./lib/resque_unit/plugin.rb
./lib/resque_unit/resque.rb
./lib/resque_unit/scheduler.rb
./lib/resque_unit/scheduler_assertions.rb
./lib/resque_unit.rb
./lib/resque_unit_scheduler.rb
./README.md
./test
./test/resque_test.rb
./test/resque_unit_scheduler_test.rb
./test/resque_unit_test.rb
./test/sample_jobs.rb
./test/test_helper.rb
~/Source/playground/resque_unit-0.4.8 jweiss$

gem install , 가장 단순한 형태로 이와 같은 일을 합니다. gem을 잡고 시스템의 특정 디렉토리에 파일을 넣습니다. gem install 위치를 확인할 수 있습니다. gem environment를 실행하면 gem이 설치됩니다. (INSTALLATION DIRECTORY:를 찾습니다. 줄):

~ jweiss$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.2.2
  - RUBY VERSION: 2.1.2 (2014-05-08 patchlevel 95) [x86_64-darwin14.0]
  - INSTALLATION DIRECTORY: /usr/local/Cellar/ruby/2.1.2/lib/ruby/gems/2.1.0
  ...
~ jweiss$ ls /usr/local/Cellar/ruby/2.1.2/lib/ruby/gems/2.1.0
bin		    bundler		doc		    gems
build_info	cache		extensions	specifications

설치된 모든 gem 코드는 gems 아래에 있습니다. 디렉토리.

이러한 경로는 시스템마다 다르며 Ruby를 설치한 방법에 따라 다릅니다(rvm은 Homebrew와 다르고 rbenv와 다릅니다). 그래서 gem environment gem의 코드가 어디에 있는지 알고 싶을 때 도움이 될 것입니다.

젬 코드는 어떻게 필요합니까?

gem 내부의 코드를 사용할 수 있도록 RubyGems는 Ruby의 require를 재정의합니다. 방법. (core_ext/kernel_require.rb에서 이 작업을 수행합니다). 의견이 매우 명확합니다.

core_ext/kernel_require.rb
  ##
  # When RubyGems is required, Kernel#require is replaced with our own which
  # is capable of loading gems on demand.
  #
  # When you call <tt>require 'x'</tt>, this is what happens:
  # * If the file can be loaded from the existing Ruby loadpath, it
  #   is.
  # * Otherwise, installed gems are searched for a file that matches.
  #   If it's found in gem 'y', that gem is activated (added to the
  #   loadpath).
  #

예를 들어 active_support를 로드하고 싶다고 가정해 보겠습니다. . RubyGems는 Ruby의 require를 사용하여 이를 요구하려고 시도합니다. 방법. 다음과 같은 오류가 발생합니다.

LoadError: cannot load such file -- active_support
	from (irb):17:in `require'
	from (irb):17
	from /usr/local/bin/irb:11:in `<main>'

RubyGems는 해당 오류 메시지를 보고 active_support.rb를 찾아야 함을 확인합니다. 대신 보석 내부. 이를 위해 gem의 메타데이터를 스캔하여 active_support.rb가 포함된 gem을 찾습니다. :

irb(main):001:0> spec = Gem::Specification.find_by_path('active_support')
=> #<Gem::Specification:0x3fe366874324 activesupport-4.2.0.beta1>

그런 다음 활성화 gem 내부의 코드를 Ruby의 로드 경로(require할 수 있는 디렉토리)에 추가합니다. 파일 출처):

irb(main):002:0> $LOAD_PATH
=> ["/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby/2.1.0/x86_64-darwin14.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin14.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/2.1.0/x86_64-darwin14.0"]
irb(main):003:0> spec.activate
=> true
irb(main):004:0> $LOAD_PATH
=> ["/usr/local/Cellar/ruby/2.1.2/lib/ruby/gems/2.1.0/gems/i18n-0.7.0.beta1/lib", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/gems/2.1.0/gems/thread_safe-0.3.4/lib", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/gems/2.1.0/gems/activesupport-4.2.0.beta1/lib", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby/2.1.0/x86_64-darwin14.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/site_ruby", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby/2.1.0/x86_64-darwin14.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/vendor_ruby", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/2.1.0", "/usr/local/Cellar/ruby/2.1.2/lib/ruby/2.1.0/x86_64-darwin14.0"]

이제 active_support 로드 경로에 있는 경우 require할 수 있습니다. Ruby 코드의 다른 부분과 마찬가지로 gem에 있는 파일입니다. require의 원래 버전을 사용할 수도 있습니다. , RubyGems가 덮어쓴 것:

irb(main):005:0> gem_original_require 'active_support'
=> true

멋지다!

약간의 지식은 먼 길을 간다

RubyGems는 복잡해 보일 수 있습니다. 하지만 가장 기본적인 수준에서는 Ruby의 로드 경로를 관리할 뿐입니다. 모든 것이 쉽다는 말은 아닙니다. RubyGems가 gem, gem 바이너리(예:railsrake ), C 확장 및 기타 많은 것들.

그러나 이 표면 수준에서도 RubyGems를 아는 것은 많은 도움이 될 것입니다. irb에서 약간의 코드 읽기 및 재생 , 당신은 당신의 보석의 근원으로 뛰어들 수 있습니다. 보석이 어디에 있는지 이해할 수 있으므로 RubyGems가 보석에 대해 알고 있는지 확인할 수 있습니다. 그리고 보석이 로드되는 방식을 알게 되면 미친 것처럼 보이는 로드 문제를 파헤칠 수 있습니다.

Rails와 Bundler가 gem을 처리하는 방법에 대해 자세히 알아보려면 다음 문서를 확인하세요. Rails는 gem을 어떻게 처리하나요?