LoginSignup
0
0

More than 5 years have passed since last update.

从零创建一个 gem

Posted at

从头到尾学习如果将自己的代码打包成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!

参考:
1. https://blog.engineyard.com/2015/its-raining-gems
2. http://bundler.io/v1.7/rubygems.html

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0