Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

อัญมณีทำงานอย่างไร?

ส่วนใหญ่อัญมณีใน 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) ความคิดเห็นค่อนข้างชัดเจน:

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 จัดการกับอัญมณีอย่างไร