如何開發一個自己的 RubyGem?
什么是 RubyGem
RubyGem是Ruby語言的標準源碼打包格式。
大家一直都在用gem這個命令,但是很少有人知道這個東西是怎么來的,這里我從網上扒下一些資料匯總一下,分享給大家。最后面會有這些鏈接,想進一步了解的,可以點進去看看。Ruby語言深受其他幾種腳本語言的影響,其中就有Perl,而Perl有個 CPAN(Comprehensive Perl Archive Network),這個東西也就像是現在的RubyGems.org,但是當時Ruby是沒有這樣一個東西的。像CPAN和RubyGem,它們僅僅是定義好的一種源碼的打包和安裝方式,另外還有一些組織,會提供這種免費的公共的源碼包的存儲,這也就現在大家每天都要使用的安裝方式:
gem install rails
在RubyGem的發展歷史當中,有幾位重要的人物,這里也作為八卦知識給大家曬一曬,就當做大家茶余飯后的談點吧。Ruby社區的人應該都知道 Jim Weirich這個人,他已經在2014年2月份去世了,是一個可愛的白胡子大叔,他和另外的四位Rich Kilmer, Chad Fowler, David Black, Paul Brannan在2003年制定了RubyGem的基本規范和實現,但是其實RubyGem最早是Ryan Leavengood在2001年開發的,可惜沒有流行起來,最后到了2003年,前面的5個人經過Ryan Leavengood的同意,使用了RubyGem這個名稱,開發了新版的RubyGem,其中并沒有使用Ryan Leavengood的代碼。這里附上rubygems的執行文件鏈接,看看注釋,里面有上面幾個人的名字 rubygems/blob/master/bin/gem
rubygems有默認的源,也可以更改,國內的基本就是https://rubygems.taobao.org了,有些公司有自己的需求,也會搭建自己的私源。當前的官方源為https://rubygems.org,這個源也是幾經輾轉,早期的Ruby用戶都知道http://gems.rubyforge.org和http://gemcutter.org,甚至github都曾經作為源使用過,也就是http://gems.github.com,這三個現在都已經棄用了。
看看,一個簡單的gem install歷史還不少啊。
RubyGem的基本使用方法
gem install rails //安裝rails gem install rails -v 4.2.0 //安裝指定版本的rails gem search rails //查找所有名稱中含有rails的gem gem search ^rails //查找所有名稱中以rails開頭的gem gem search ^rails -d //查找所有名稱中以rails開頭的gem,并顯示描述 gem build package.gemspec //構建一個gem,就是把你自己寫的gem源碼,打包成一個.gem文件 gem push pack-1.0.gem //發布到源上,默認是rubygems.org
這里只是簡單列出了最常用的使用方法,大家看看就好,命令很有限,也很簡單,執行gem --help,基本上所有的東西你都能10分鐘內學會。
如何制作一個自己的RubyGem
前幾年還是有這樣那樣的工具,現在用bundler就夠了。
$ bundler gem mygem
create mygem/Gemfile
create mygem/Rakefile
create mygem/LICENSE.txt
create mygem/README.md
create mygem/.gitignore
create mygem/mygem.gemspec
create mygem/lib/mygem.rb
create mygem/lib/mygem/version.rb
Initializing git repo in /home/lizhe/Workspace/mygem一個bundler命令就搞定了。來看看mygem這個文件夾下的東西:
total 24 -rw-rw-r-- 1 lizhe lizhe 90 7月 2 15:52 Gemfile drwxrwxr-x 3 lizhe lizhe 4096 7月 2 15:52 lib -rw-rw-r-- 1 lizhe lizhe 1062 7月 2 15:52 LICENSE.txt -rw-rw-r-- 1 lizhe lizhe 850 7月 2 15:52 mygem.gemspec -rw-rw-r-- 1 lizhe lizhe 29 7月 2 15:52 Rakefile -rw-rw-r-- 1 lizhe lizhe 556 7月 2 15:52 README.md
現在來看看gemspec這個文件,它描述了這個Gem的各種信息
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'mygem/version'
Gem::Specification.new do |spec|
spec.name = "mygem"
spec.version = Mygem::VERSION
spec.authors = ["lizhe"]
spec.email = ["lizhe@oneapm.com"]
spec.summary = %q{TODO: Write a short summary. Required.}
spec.description = %q{TODO: Write a longer description. Optional.}
spec.homepage = ""
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"
end
我發現有人看到這個文件的內容時,倒是關心那個'git ls-files -z'.split("\x0")是什么意思?以及那個\x0是什么?附上一個鏈接,解釋一下,參考鏈接。這個文件最上面先把lib文件夾添加到load path中,Gem::Specification的第一部分主要是描述這個gem的信息,包括名稱,版本等等,第二部分是這個gem都包括哪些文件,執行文件,測試文件以及哪些路徑下的文件可以添加到load path中。第三部分是開發mygem需要依賴的其他gem。這些信息都可以自定義,先按照默認走。讓我們build第一個gem吧。
$ rake build
rake aborted!
WARNING: See http://guides.rubygems.org/specification-reference/ for help
ERROR: While executing gem ... (Gem::InvalidSpecificationException)
"FIXME" or "TODO" is not a description
/home/lizhe/.rvm/gems/ruby-2.1.5@global/gems/bundler-1.7.12/lib/bundler/gem_helper.rb:149:in `sh'
/home/lizhe/.rvm/gems/ruby-2.1.5@global/gems/bundler-1.7.12/lib/bundler/gem_helper.rb:57:in `build_gem'
/home/lizhe/.rvm/gems/ruby-2.1.5@global/gems/bundler-1.7.12/lib/bundler/gem_helper.rb:39:in `block in install'
/home/lizhe/.rvm/gems/ruby-2.1.5@global/bin/ruby_executable_hooks:15:in `eval'
/home/lizhe/.rvm/gems/ruby-2.1.5@global/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => build
(See full trace by running task with --trace)這個警告是提醒我們需要替換gemspec中的FIXME和TODO,這個警告如果不解決是無法build一個gem的,直接刪除掉summary和description中的TODO:
spec.summary = %q{Write a short summary. Required.}
spec.description = %q{Write a longer description. Optional.}
再來執行:
$ rake build mygem 0.0.1 built to pkg/mygem-0.0.1.gem.
好了,第一個gem誕生了。它就在當前目錄的pkg下:mygem-0.0.1.gem。如何使用呢?不考慮bundler的情況下,如果你開起了一個irb或者pry的session時,一般都會這樣寫:require "mygem",如果你現在這樣做,那肯定不行,因為它還沒有被安裝到ruby的load path中,那就把它安裝上。
$ rake install mygem 0.0.1 built to pkg/mygem-0.0.1.gem. mygem (0.0.1) installed.
安裝好了,那就來使用一下,打開irb:
require "mygem" => true Mygem => Mygem
看,已經可以使用這個module了,不過這個gem啥也干不了,那么我們就給它添加一個方法吧,打開lib/mygem.rb,添加一個方法:
require "mygem/version" module Mygem def self.hello p "hello from my gem" end end
保存,然后執行rake install,這個命令會先build然后install,再重新打開irb:
require "mygem" => true Mygem.hello => "hello from my gem"
能夠正常運行了,那就來發布第一個gem吧:
rake release // 輸入你在rubygems.org上的賬號和密碼
如果你的一個rails應用正好需要輸出一個hello from my gem,那么現在你可以在Gemfile中添加這個gem了:
gem 'mygem'
添加完執行bundle install,你就可以在你的rails應用中使用它了。
參考鏈接: