読者です 読者をやめる 読者になる 読者になる

脳汁portal

アメリカ在住(だった)新米エンジニアがその日学んだIT知識を書き綴るブログ

gemファイルを作成して公開する方法

ruby

自作のgemを開発してrubygems.orgへ公開する方法です。
RubyGems.org | your community gem host

  • 今回はto_arrayという名前のgemを作りたいと思います。

to_array

arrayがto_strメソッドによってstringに変換されてしまったり、文字列で返ってきた場合に文字列からArrayに変換する

実装

1. 開発環境準備
$ bundle gem to_array -t

Creating gem 'to_array'...
MIT License enabled in config
      create  to_array/Gemfile
      create  to_array/.gitignore
      create  to_array/lib/to_array.rb
      create  to_array/lib/to_array/version.rb
      create  to_array/to_array.gemspec
      create  to_array/Rakefile
      create  to_array/README.md
      create  to_array/bin/console
      create  to_array/bin/setup
      create  to_array/LICENSE.txt
      create  to_array/.travis.yml
      create  to_array/.rspec
      create  to_array/spec/spec_helper.rb
      create  to_array/spec/to_array_spec.rb
2. 実際の処理を実装する
  • lib/to_array.rbへ実装します。

最初はこのようなファイル内容です。

require "to_array/version"

module ToArray
  # Your code goes here...
end

↓これをこのように変更しました

class String
  def to_array
    if self[0] != "[" || self[-1] != "]"
      raise ArgumentError.new("invalid value for `str_to_array': '#{self}'")
    end

    begin
      arr = self.chomp.gsub(/"|^\[|\]$/, '')
      arr = arr.split(/,[\s]*/)
      return arr
    rescue
      raise ArgumentError.new("invalid value for `str_to_array': '#{self}'")
    end
  end
end
3. 実際の動きを確認する

rubyのファイルを作成してもいいですが、今回はirbで確認します。

$ irb
### 作成したruby ファイルをrequire
2.1.2 :001 > require_relative './lib/to_array'
 => true

### その後は実装したメソッドを確認する
2.1.2 :005 > str = ['foo', 'bar', 'fizz', 'bazz'].to_s
 => "[\"foo\", \"bar\", \"fizz\", \"bazz\"]"
2.1.2 :007 > str.class
 => String
2.1.2 :008 > str.size
 => 30

2.1.2 :009 > reconverted = str.to_array
 => ["foo", "bar", "fizz", "bazz"]
2.1.2 :011 > reconverted.class
 => Array
2.1.2 :012 > reconverted.size
 => 4

問題ないですね。

# テストの作成

  • spec/to_array_spec.rb内にテスト内容を記述します
  • テストライブラリはrspecです

今回は以下のようにしました

require 'spec_helper'

describe ToArray do
  arr1 = ['foo', 'bar', 'fizz', 'bazz']
  str1 = arr1.to_s

  context "success case" do
    it 'should send back ArrayClass' do
      expect(str1.to_array).to be_a_kind_of(Array)
    end

    it 'should array size is same' do
      expect(str1.to_array.size).to eq(arr1.size)
    end
  end

  context "failure case(Other Object)" do
    it 'nil' do
      expect{nil.to_array}.to raise_error(NoMethodError)
    end
    it 'boolean' do
      expect{true.to_array}.to raise_error(NoMethodError)
    end
    it 'Already Array' do
      expect{arr1.to_array}.to raise_error(NoMethodError)
    end
    it 'Interger' do
      expect{100.to_array}.to raise_error(NoMethodError)
    end
    it 'Hash' do
      expect{{'foo'=>'bar', 'fizz'=>'bazz'}.to_array}.to raise_error(NoMethodError)
    end
  end

  context "failure case(Other Object)" do
    it 'nil' do
      expect{nil.to_array}.to raise_error(NoMethodError)
    end
    it 'boolean' do
      expect{true.to_array}.to raise_error(NoMethodError)
    end
    it 'Already Array' do
      expect{arr1.to_array}.to raise_error(NoMethodError)
    end
    it 'Interger' do
      expect{100.to_array}.to raise_error(NoMethodError)
    end
    it 'Hash' do
      expect{{'foo'=>'bar', 'fizz'=>'bazz'}.to_array}.to raise_error(NoMethodError)
    end
  end
end

実際に確認します

$ rspec

ToArray
  success case
    should send back ArrayClass
    should array size is same
  failure case(Other Object)
    nil
    boolean
    Already Array
    Interger
    Hash
  failure case(Other Object)
    nil
    boolean
    Already Array
    Interger
    Hash

Finished in 0.00638 seconds (files took 0.06421 seconds to load)
12 examples, 0 failures

ここまで出来れば大体OKです。
あとはリリースの準備をします

リリース準備

README.mdを作成する
  • 既にテンプレートが作成されてありますが、こちらを編集して使い方やダウンロード方法等を記入しておきましょう。
  • 記法はMARKDOWN記法です
version番号の設定(任意)
  • lib/to_array/version.rbのversion番号を変更しましょう。
  • 最初なら1.0.0とかでいいでしょう。
module ToArray
  VERSION = "1.0.0"
end
gemの情報を入力する

to_array.gemspecの中のTODOと書かれている部分を修正しましょう

$ grep -r 'TODO' to_array.gemspec
  spec.authors       = ["TODO: Write your name"]
  spec.email         = ["TODO: Write your email address"]
  spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
  spec.description   = %q{TODO: Write a longer description or delete this line.}
  spec.homepage      = "TODO: Put your gem's website or public repo URL here."
    spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"

リリース

確認
$ rake -T
rake build          # Build to_array-1.0.0.gem into the pkg directory
rake install        # Build and install to_array-1.0.0.gem into system gems
rake install:local  # Build and install to_array-1.0.0.gem into system gems without network access
rake release        # Create tag v1.0.0 and build and push to_array-1.0.0.gem to Rubygems
rake spec           # Run RSpec code examples

$ rake install:local
to_array 1.0.0 built to pkg/to_array-1.0.0.gem.
to_array (1.0.0) installed.

$ irb
2.1.2 :001 > require 'to_array'
 => true
2.1.2 :002 >  ['foo', 'bar'].to_s.to_array.class
 => Array
2.1.2 :003 > ['foo', 'bar'].to_s.to_array.size
 => 2

$ rake spec
ToArray
  success case
    should send back ArrayClass
    should array size is same
  failure case(Other Object)
    nil
    boolean
    Already Array
    Interger
    Hash
  failure case(Other Object)
    nil
    boolean
    Already Array
    Interger
    Hash

Finished in 0.00833 seconds (files took 0.06756 seconds to load)
12 examples, 0 failures

問題なければupload

upload
$ gem push pkg/to_array-1.0.0.gem
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at https://rubygems.org/sign_up
   Email:   ******************
Password:

Signed in.
Pushing gem to https://rubygems.org...
Successfully registered gem: to_array (1.0.0)

これで無事リリースすることが出来ました。
to_array | RubyGems.org | your community gem host