ส่วนใหญ่อัญมณีใน Ruby Just Work แต่มีปัญหาใหญ่กับเวทมนตร์ของ Ruby เมื่อมีสิ่งผิดปกติเกิดขึ้น ยากที่จะหาสาเหตุ
คุณจะไม่มีปัญหากับอัญมณีของคุณบ่อยๆ แต่เมื่อคุณทำเช่นนั้น Google ก็ไม่มีประโยชน์อย่างน่าประหลาดใจ ข้อความแสดงข้อผิดพลาดเป็นข้อความทั่วไป ดังนั้นจึงอาจมีสาเหตุหลายประการ และถ้าคุณไม่เข้าใจว่าอัญมณีทำงานจริงกับ Ruby อย่างไร คุณจะต้องลำบากในการแก้จุดบกพร่องของปัญหาเหล่านี้ด้วยตัวของคุณเอง
อัญมณีอาจ ดูเหมือน มีมนต์ขลัง แต่ด้วยการสอบสวนเพียงเล็กน้อย ก็เข้าใจได้ง่าย
gem install
คืออะไร ทำอย่างไร
Ruby gem เป็นเพียงโค้ดบางส่วนที่บีบอัดด้วยข้อมูลพิเศษเล็กน้อย คุณสามารถดูรหัสภายในอัญมณีด้วย gem unpack
:
~/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 install
จะติดตั้งอัญมณีของคุณหากคุณเรียกใช้ gem environment
(มองหา 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
รหัสอัญมณีที่คุณติดตั้งทั้งหมดจะอยู่ใต้ gems
ไดเรกทอรี
เส้นทางเหล่านี้แตกต่างกันไปในแต่ละระบบ และขึ้นอยู่กับว่าคุณติดตั้ง Ruby อย่างไร (rvm แตกต่างจาก Homebrew ซึ่งแตกต่างจาก rbenv เป็นต้น) ดังนั้น gem environment
จะเป็นประโยชน์เมื่อคุณต้องการทราบว่ารหัสอัญมณีของคุณอยู่ที่ไหน
ต้องใช้รหัสอัญมณีอย่างไร
เพื่อช่วยให้คุณใช้รหัสภายในอัญมณีของคุณ RubyGems จะแทนที่ require
ของ Ruby กระบวนการ. (ทำสิ่งนี้ใน 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 จะพยายามกำหนดให้ใช้ require
ของ Ruby กระบวนการ. นั่นทำให้คุณมีข้อผิดพลาดนี้:
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
ภายในอัญมณีแทน โดยจะสแกนข้อมูลเมตาของอัญมณีเพื่อค้นหาอัญมณีที่มี active_support.rb
:
irb(main):001:0> spec = Gem::Specification.find_by_path('active_support')
=> #<Gem::Specification:0x3fe366874324 activesupport-4.2.0.beta1>
จากนั้น เปิดใช้งาน gem ซึ่งเพิ่มรหัสภายใน 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
ไฟล์ใน gem เหมือนกับโค้ด Ruby อื่นๆ คุณยังสามารถใช้เวอร์ชันดั้งเดิมของ require
, อันที่ RubyGems เขียนทับ:
irb(main):005:0> gem_original_require 'active_support'
=> true
เจ๋ง!
ความรู้เล็กๆ น้อยๆ มีประโยชน์มากมาย
RubyGems อาจดูซับซ้อน แต่ในระดับพื้นฐานที่สุด มันเป็นเพียงการจัดการเส้นทางโหลดของ Ruby สำหรับคุณ ไม่ได้หมายความว่ามันง่ายทั้งหมด ฉันไม่ได้พูดถึงวิธีที่ RubyGems จัดการเวอร์ชันที่ขัดแย้งกันระหว่าง gem, gem binaries (เช่น rails
และ rake
), นามสกุล C และอื่นๆ อีกมากมาย
แต่การรู้จัก RubyGems แม้ในระดับพื้นผิวนี้จะช่วยได้มาก ด้วยการอ่านและเล่นโค้ดเล็กน้อยใน irb
คุณจะสามารถดำดิ่งสู่แหล่งอัญมณีของคุณได้ คุณสามารถเข้าใจว่าอัญมณีของคุณอาศัยอยู่ที่ไหน ดังนั้นคุณจึงมั่นใจได้ว่า RubyGems รู้เกี่ยวกับอัญมณีเหล่านั้น และเมื่อคุณทราบวิธีการโหลดอัญมณีแล้ว คุณก็จะสามารถเจาะลึกปัญหาการโหลดที่ดูบ้าๆ ได้
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีที่ Rails และ Bundler จัดการกับอัญมณี โปรดอ่านบทความนี้:Rails จัดการกับอัญมณีอย่างไร