Ruby gem คืออะไร?
Gem คือแพ็กเกจที่คุณดาวน์โหลดและติดตั้ง เมื่อคุณ require gem ที่ติดตั้งแล้ว คุณเพิ่ม functionality เพิ่มเติมให้โปรแกรม Ruby ของคุณ
Gems อนุญาตให้คุณ:
- เพิ่มฟีเจอร์ login ให้ Rails app
- ทำงานกับ external services (เช่น APIs) ได้ง่าย
- สร้าง web application
นี่แค่ตัวอย่าง ทุก gem มีเป้าหมายของตัวเอง
ทำไมเราใช้ gems?
- เป็นวิธีที่เราแชร์ libraries และ tools ใน Ruby
- โครงสร้างไฟล์และรูปแบบของ gem ทำให้เข้าใจง่ายว่ามันทำงานอย่างไร
- Specification file (".spec") ที่มาพร้อมทุก gem อธิบาย dependencies (gems อื่นที่ต้องการ) เพื่อให้โค้ดมีทุกอย่างที่ต้องการทำงาน
ขอบคุณ RubyGems เรามี ecosystem อุดมสมบูรณ์ของ libraries ที่มีประโยชน์ เพียงหนึ่ง gem install!
รายการ gems ที่จำเป็นสำหรับโปรเจกต์ (non-gem) ใดๆ สามารถระบุในไฟล์พิเศษชื่อ "Gemfile" ได้ เพื่อให้ติดตั้งอัตโนมัติโดย Bundler ทั้งสองครอบคลุมในคู่มือนี้
ตัวอย่าง gems:
- Rails และ components ทั้งหมด (ActiveRecord, ActiveSupport ฯลฯ) แจกจ่ายเป็น Ruby gems
- Pry, alternative อันทรงพลังของ irb
- Nokogiri, XML และ HTML parser ยอดนิยม
Gems ส่วนใหญ่เป็น pure Ruby code
Gem บางตัว include Ruby C extension สำหรับประสิทธิภาพที่ดีขึ้น
Extension นี้ build อัตโนมัติเมื่อคุณติดตั้ง gem ในบางกรณี คุณอาจต้องติดตั้ง software เพิ่มเติมที่ไม่ได้จัดการโดย RubyGems
ตอนนี้:
มาเรียนรู้ gems มากขึ้นโดยสร้างของตัวเองและ看看ไฟล์ที่ประกอบ gem
วิธีสร้าง RubyGem
คุณเตรียมไฟล์สำหรับ gem ใหม่โดยรัน bundle gem <name>
ตัวอย่าง:
bundle gem awesome_gem
Gem ประกอบด้วยโครงสร้างต่อไปนี้:
├── awesome_gem.gemspec
├── bin
│ ├── console
│ └── setup
├── Gemfile
├── lib
│ ├── awesome_gem
│ │ └── version.rb
│ └── awesome_gem.rb
├── Rakefile
├── README.md
└── test
├── awesome_gem_test.rb
└── test_helper.rb
ไฟล์ .gemspec นี้คือที่คุณ จะพบข้อมูลทั้งหมดเกี่ยวกับ gem
รวมถึง:
- Gem name
- Gem summary (คำอธิบายสั้น)
- Author name
- Dependency list
- รายการไฟล์ที่จะ include ใน gem
- Optional: อีเมล author, project URL (homepage), executables, c extensions, long description.
Gem version เองถูกนิยามเป็น constant ใน lib/<gem_name>/version.rb
ตัวอย่าง gemspec:
Gem::Specification.new do |spec| spec.name = "awesome_gem" spec.version = AwesomeGem::VERSION spec.authors = ["Jesus Castello"] spec.summary = "Example gem for article about Ruby gems" spec.files = Dir['**/**'].grep_v(/.gem$/) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.16" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "minitest", "~> 5.0" end
อาร์เรย์ require_paths คือที่ Ruby จะมองหาไฟล์ gem ของคุณเมื่อ require มัน สิ่งนี้อนุญาตให้คุณวางโค้ดภายใต้ lib/<gem_name>/ และ require ด้วย require "<gem_name>/<file_name>"
ตัวอย่าง:
ไฟล์ชื่อ lib/awesome_gem/parser.rb จะ require เป็น require "awesome_gem/parser" จากที่ไหนก็ได้ภายใน gem
คุณจะมี requires ส่วนใหญ่ใน lib/<gem_name>.rb (ไฟล์เดียวที่ root ของ /lib)
นั่นคือไฟล์ที่โหลดเมื่อคุณ require gem!
ต่อไป:
บรรทัด add_development_dependency นิยาม gems ที่คุณใช้ระหว่าง development
เหล่านี้คือ gems เช่น minitest, RSpec, หรือ pry
ในขณะที่ add_dependency นิยาม gems ที่คุณใช้เป็นส่วนหนึ่งของโค้ด
เมื่อคุณเปลี่ยน summary และ description จากค่า default… คุณจะโหลด irb session พร้อม gem ได้ด้วยโปรแกรม bin/console ที่ bundle gem สร้างให้
ตัวอย่าง:
$ bin/console irb(main):001:0> irb(main):002:0> irb(main):003:0> AwesomeGem => AwesomeGem irb(main):004:0> irb(main):005:0> AwesomeGem::VERSION => "0.1.0"
จากนั้นคุณ package gem ด้วย gem build <name>.gemspec และ publish ไป rubygems.org ด้วย gem push
Bundler คืออะไร?
ระหว่างเรียนรู้ Ruby gems คุณอาจอ่านเกี่ยว Bundler
แต Bundler คืออะไรแน่?
Bundler เป็นเครื่องมือสำหรับ dependency management
RubyGems ไม่จัดการแล้วหรือ?
จัดการ… แต เฉพาะสำหรับ gems เอง
Regular Ruby application ของคุณไม่ได้สร้างเป็น gem ดังนั้นไม่ได้ feature นี้
นั่นคือเหตุผลที่ Bundler มีอยู่!
เข้าใจ Gemfiles
เคยเห็นไฟล์ Gemfile ไหม?
นั่นคือที่คุณเขียน gems ที่อยากใช้สำหรับ Ruby application ของคุณ
Gems นี้จะโหลดให้คุณโดยไม่ต้อง require
Gemfile 长这样:
ruby '2.5.0' gem 'rails', '~> 5.2.1' gem 'sqlite3' gem 'puma', '~> 3.11' gem 'bootsnap', '>= 1.1.0', require: false
Bundler (และ RubyGems ตั้งแต่ version 2.0) อ่านไฟล์นี้และติดตั้ง version ที่ขอของ gems เหล่านี้
นี่คือสิ่งที่คุณควรเห็นเมื่อรันคำสั่ง bundle install:
Using turbolinks-source 5.1.0 Using turbolinks 5.1.1 Using uglifier 4.1.18 Using web-console 3.6.2 Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.
ตอนนี้:
สัญลักษณ์เหล่านี้ (เช่น ~>) ใช้ตอนประกาศ version สำหรับทุก gem ใน Gemfile ทำอะไร?
พวกมันอนุญาตให้คุณขอ ช่วงของ versions
คุณพูดได้ว่ "อยากให้ version เท่ากับหรือมากกว่า 1.2 แต่น้อยกว่า 2.0"
จะ长这样:
gem 'puma', '~> 1.2'
~> เป็น shortcut สำหรับช่วงนี้:
gem 'puma', '>= 1.2', '< 2.0'
ในกรณี ~> 5.2.1 หมายถึง พอดีกับนี้:
'>= 5.2.1', '< 5.3'
ยิ่ง version number specific ยิ่ง version range restricted
Gemfile Options และ Gemfile.lock
คุณมี options หลายอย่างตอน require gem ใน Gemfile
ตัวอย่าง:
คุณอาจอยากดึง gem จาก source อื่น เช่น GitHub
นี่ ช่วยเมื่อต้องการ latest version ของโปรเจกต์ แม้ยังไม่ released บน rubygems.org
ตัวอย่าง:
gem "rails", git: "git@github.com:rails/rails.git"
คุณส่ง option branch ใช้ code จาก branch ที่ไม่ใช่ master
แบบนี้:
gem "awesome_print", git: "git@github.com:awesome-print/awesome_print.git", branch: "v2"
Option อีกอย่างคือ require: false
มันทำอะไร?
บอก Bundler อย่า auto-require gem ให้ หมายถึงคุณต้อง require เองในโค้ดเมื่อต้องการ
ใช้สำหรับ gems ที่จำกัด scope
ตัวอย่าง:
Gems ที่ใช้ใน rake task เฉพาะ แตไม่ใช้ใน Rails controllers และ models ประโยชน์คือประหยัด memory ใน app code เพราะโหลด gem เฉพาะตอนต้องการ
คุณยัง group gems by environment ได้
หมายถึง gems ที่ติดตั้งและโหลดเฉพาะ development (เช่น capybara และ pry)
สุดท้าย bundler สร้าง Gemfile.lock
ความแตกต่างคืออะไร?
Gemfile.lock เป็น auto-generated และบอก exactly versions ของทุก gem ที่ติดตั้ง
Bundler จะติดตั้ง versions เหล่านี้ ดังนั้นเมื่อ deploy application ไป production หรือแชร์โปรเจกต์กับนักพัฒนาคนอื่น ทุกคนจะทำงานกับชุด gems เหมือนกันทุกประการ
คำสั่ง Gem และ Bundler ที่มีประโยชน์
| Command | Description |
|---|---|
| gem list | รายการ gems ติดตั้งทั้งหมด รับ argument สำหรับ filter gems by name (ตัวอย่าง: gem list active) |
| gem which <name> | ให้ path ที่ gem ติดตั้ง |
| gem search <name> | ค้นหา gems จาก sources ที่ config (default: rubygems.org) รับ regular expression (ตัวอย่าง: gem search "\Aawesome_") |
| gem env | แสดงข้อมูล gem environment (version, paths, configuration) |
| gem install <name> -v <version> | ติดตั้ง gem version เฉพาะ (ตัวอย่าง: gem install sinatra -v 2.0.0) |
| bundle viz | สร้าง visualization ของ dependency graph โปรเจกต์ปัจจุบัน |
| bundle show | แสดง info gem ตัวหนึ่งที่ติดตั้ง via bundler ต้องอยู่ใน folder ที่มี Gemfile |
| bundle outdated | แสดงรายการ outdated gems โปรเจกต์ปัจจุบัน ใช้ option --groups group ได้ |
| bundle console | รัน irb session พร้อม gems จาก Gemfile โปรเจกต์ปัจจุบัน |
สรุป
คุณเรียนรู้เกี่ยวกับ RubyGems ระบบแพ็กเกจสำหรับ Ruby คุณยังเรียนรู้โครงสร้าง gem, Gemfile, Bundler และความแตกต่างระหว่าง Gemfile และ Gemfile.lock
หวังว่าจะมีประโยชน์!
กรุณาแชร์บทความนี้ สมัครรับจดหมายข่าวหายังไม่ (9000+ Ruby developers!) และดู Ruby book ของผม
ขอบคุณที่อ่าน และขอให้วันที่ดี 🙂