创建你自己的gem

make your own gem

从头到尾学习如果将自己的代码打包成gem

  • Introduction
  • Your first gem
  • Requiring more files
  • Adding an executable
  • Writing tests
  • Documenting your code
  • Wrapup

介绍

通过rubygem内置的工具就能够轻松的打包代码为gem.让我们来创建一个简单的hello world的gem.

第一个gem

创建一个名为hola的gem.还有一个gemspec,目录结构如下:

    -hola.gemspec
    `--lib
        `--hola.rb

其实关键的你代码是放在lib文件夹里面的,有一个约定就是要有一个和你的gem名称一样的ruby文件.
这样的话,就可以直接通过require 'hola'来引用此gem了.此文件就是gem的入口.
看看在lib/hola.rb的内容:

class Hola  
  def self.hi
    puts "Hello world!"
  end
end  

下面来看一些gemspec文件里定义了什么内容,其他不外乎就是谁写的,版本,依赖等.

Gem::Specification.new do |s|  
  s.name        = 'hola'
  s.version     = '0.0.0'
  s.date        = '2010-04-28'
  s.summary     = "Hola!"
  s.description = "A simple hello world gem"
  s.authors     = ["Nick Quaranto"]
  s.email       = 'nick@quaran.to'
  s.files       = ["lib/hola.rb"]
  s.homepage    =
    'http://rubygems.org/gems/hola'
  s.license       = 'MIT'
end  

看着眼熟?其实就是ruby代码了.
关于到底有什么能够放在里面,可以参照这里.
创建gemspec之后,就可以build一个gem 了.之后就可以安装build之后的gem了.
通过此命令

gem build hola.gemspec

你可以看见如下的控制台输出:

Successfully built RubyGem  
Name: hola  
Version: 0.0.0  
File: hola-0.0.0.gem

% gem install ./hola-0.0.0.gem
Successfully installed hola-0.0.0  
1 gem installed  

当然要确保能够使用,还需实际的使用它啊,通过reuqire

irb
require ‘hola’
true
Hola.hi

可以看见输出hello world了.那就表示成功了一大步.之后就可以准备发布到rubygem了.
首先要配置登录到rubygem的信息:

> curl -u yourusername_on_rubygem
https://rubygems.org/api/v1/api_key.yaml >  
~/.gem/credentials; chmod 0600 ~/.gem/credentials

Enter host password for user 'yourusername_on_rubygem':

如果系统限制等,无法使用curl,openssl等,可以通过浏览器访问链接`https://rubygems.org/api/v1/api_key.yaml`,它会让你登录的,
成功则会下载一个认证信息文件`api_key.yaml`,完了直接把它放到~/.gem/文件夹下,重命名为**credentials**

一切设置妥当之后,就可以push你的gem了

gem push hola-0.0.0.gem

    Pushing gem to RubyGems.org...
    Successfully registered gem: hola (0.0.0)

上传过一会儿你就可以通过下面命令check到你的gem了:

gem list -r hola

然后尝试安装:

gem install hola

一切OK~

我们来个复杂点的

修改lib/hola.rb

class Hola  
  def self.hi(language = "english")
    translator = Translator.new(language)
    translator.hi
  end
end

class Hola::Translator  
  def initialize(language)
    @language = language
  end

  def hi
    case @language
    when "spanish"
      "hola mundo"
    else
      "hello world"
    end
  end
end  

上面的代码已经很拥挤了.我们把Translator这个类拆分到单独的文件中,之前提到的是把所有的ruby文件都放到lib
目录. 我们可以把目录结构调整成下面的样子:

    ├── hola.gemspec
    └── lib
        ├── hola
        │   └── translator.rb
        └── hola.rb

之后在原来lib/hola.rb的文件需要修改一下:

    require 'lib/translator'
    class Hola
        def self.hi(language = "english")
            translator = Translator.new(language)
            translator.hi
      end
    end

接着还要修改一下gemspec文件,把新添加的目录和文件索引进去,不然到时候打包的时候新文件不会被打包进去:

        ...
        s.files       = ["lib/hola.rb", "lib/hola/translator.rb"]
        ...

添加一个可执行的文件

gem不仅仅只是提供一些ruby code. 同时还暴漏了一些可执行的文件到你当前的shell目录下.如rake. 还有一个比较有趣的工具就是
prettify_json.rb,包含在json的gem包,它能够用来format输出json.

    curl -s http://jsonip.com/ | 
      prettify_json.rb
    {
      "ip": "24.60.248.134"
    }

其实往gem里添加可执行的文件也很简单.把他们放到bin/目录.然后在gemspec里添加他们.让我们继续在hola的gem里修改:

    % mkdir bin
    % touch bin/hola
    % chmod a+x bin/hola

这个bin/hola文件第一行要添加#!来告诉机器用什么目录执行它.

#!/usr/bin/env ruby

require 'hola'  
puts Hola.hi(ARGV[0])  

之后在gemspec文件里添加可执行的文件配置说明:

  s.name        = 'hola'
  s.version     = '0.0.1'
  s.executables << 'hola'  #可执行文件

编写测试

测试自己的gem非常重要,不仅仅是确保自己的代码能够工作,而且能够帮助别人.很多人通过测试用例的质量来衡量
代码质量.gem支持如果在gem里有测试的话在下载完之后自动执行测试的功能.

TEST YOUR GEM!

TEST::Unit是ruby内置的测试框架,有很多的教程在网上可以找到.同样还有很多其他的测试框架如RSpec.
不管怎么样,我们来添加测试吧.
首先创建文件Rakefile和文件夹test:

    .
    ├── Rakefile
    ├── bin
    │   └── hola
    ├── hola.gemspec
    ├── lib
    │   ├── hola
    │   │   └── translator.rb
    │   └── hola.rb
    └── test
        └── test_hola.rb

编辑test_hola.rb:

require 'test/unit'  
require 'hola'

class HolaTest < Test::Unit::TestCase  
  def test_english_hello
    assert_equal "hello world",
      Hola.hi("english")
  end

  def test_any_hello
    assert_equal "hello world",
      Hola.hi("ruby")
  end

  def test_spanish_hello
    assert_equal "hola mundo",
      Hola.hi("spanish")
  end
end  

Rakefile里添加一些简单的测试test task:

require 'rake/testtask'

Rake::TestTask.new do |t|  
  t.libs << 'test'
end

desc "Run tests"  
task :default => :test  

之后执行rake test或者直接rake来执行测试:

    % rake test
    (in /Users/qrush/Dev/ruby/hola)
    Loaded suite
    Started
    ...
    Finished in 0.000736 seconds.

    3 tests, 3 assertions, 0 failures, 0 errors, 0 skips

    Test run options: --seed 15331

you made it!

文档

大部分的gem会使用默认内建RDoc来生成文档.有很多的教程可以学习.

# The main Hola driver
class Hola  
  # Say hi to the world!
  #
  # Example:
  #   >> Hola.hi("spanish")
  #   => hola mundo
  #
  # Arguments:
  #   language: (String)

  def self.hi(language = "english")
    translator = Translator.new(language)
    puts translator.hi
  end
end  

结尾

至此已经完成了一个简单的gem,很多东西需要继续学习深究,ENJOY IT!

Written with StackEdit.