Ruby
rubygems

君がOpsでもRubyで書いたライブラリはGemで配ろう

More than 3 years have passed since last update.

Infrastracture as code流行の副産物として、もうOpsはある程度Rubyでライブラリを書けるようになりました。

折角Rubyでライブラリを書いたなら、安全&ラクに配布するためGemパッケージにしましょう、出来る人には今更でしょうが知らない人は真似してみてね。

ちなみに意外と誤解されてる点、gemにする=Rubygems.orgで公開する、ではありません、してもOKというだけで。


目標

gemファイルを置いて、gemコマンドで自分のライブラリをサーバに導入する。

こんなかんじで。

gem install -l my_libs-0.0.1.gem

じゃあやってみましょう。


Gemの雛形をつくろう

Gemの作り方は色々あるようですが、私はもっぱらbundlerです。

bundle gemで必要なファイル群を作成します、便利ですね。


Shell

$ bundle gem my_libs

create my_libs/Gemfile
create my_libs/Rakefile
create my_libs/LICENSE.txt
create my_libs/README.md
create my_libs/.gitignore
create my_libs/my_libs.gemspec
create my_libs/lib/my_libs.rb
create my_libs/lib/my_libs/version.rb

作られたファイルで、触るのはこれだけ。

ファイル名
役割

my_libs.gemspec
gemの説明と、依存する他のrubygemsがあればそれを記述します。設定ファイルのコメントくらいに捉えていればOK。

lib/my_libs/version.rb
このgemバージョンを書きます、zoneファイルのシリアルよろしく何かする度適当に増やしていきましょう。

lib/my_libs.rb
自前の関数をここに書きましょう。

メインはlib/my_libs.rbです。


概要をgemspecに

初めにこのGemが何するものぞを記述する必要があります、特に難しいことではありません。

my_libs.gemspecの初期状態はこのようになっています。


my_libs.gemspec(initial)

# coding: utf-8

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'my_libs/version'

Gem::Specification.new do |spec|
spec.name = "my_libs"
spec.version = MyLibs::VERSION
spec.authors = ["sawanoboly"]
spec.email = ["sawanoboriyu@higanworks.com"]
spec.description = %q{TODO: Write a gem description}
spec.summary = %q{TODO: Write a gem summary}
spec.homepage = ""
spec.license = "MIT"

spec.files = `git ls-files`.split($/)
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.3"
spec.add_development_dependency "rake"
end


親切なことにTODOがありますね、my_libs.gemspecこの2行を編集します。


my_libs.gemspec

  spec.description   = %q{TODO: Write a gem description}

spec.summary = %q{TODO: Write a gem summary}

descriptionsummaryは意味的にそのままですが、今回は特に区別しません。短めにgemの説明を書いておきましょう。


my_libs.gemspec

  spec.description   = %q{ruby sample libs for me}

spec.summary = %q{ruby sample libs for me}


依存するRubyGems

自前ライブラリ内で他のgemを使いたいことがある場合はmy_libs.gemspecに追加しておきます。

RubyGems.orgで公開されているtwitterが必要なら適当な箇所に1行この様に書けばOK、gem install実行時に警告を出してくれます。


my_libs.gemspec

  spec.add_dependency 'twitter'


今回は特に何も追加せずに先へいきましょう。


my_libを読み込んでみる

この時点ですでに他のgemのように機能します、中身はカラですが読み込んでみましょう。

Rubyの対話型インタプリタIrbを起動します。


Irb

$ bundle exec irb

> require 'my_libs'
=> true
> MyLibs
MyLibs
> MyLibs::VERSION
=> "0.0.1"


ライブラリを書こう

ではmy_libs/lib/my_libs.rbに自前ライブラリを書いて行きましょう、初期状態は下記です。


my_libs/lib/my_libs.rb

require "my_libs/version"

module MyLibs
# Your code goes here...
end


こちらもわかりやすく# Your code goes here…となっています。

サンプルとして外から呼べるhelloとinclude/extend用のhello2メソッドを実装します。


my_libs/lib/my_libs.rb

require "my_libs/version"

module MyLibs
def self.hello
'hello gem!'
end

def hello2
'hello gem! 2'
end
end


モジュールを記述したので、先程の要領で読み込んで使っていきましょう。


ライブラリのメソッドを実行しよう


Irb

$ bundle exec irb

> require 'my_libs'
=> true

> MyLibs.methods(false)
=> [:hello]

> MyLibs.hello
=> "hello gem!"

> include MyLibs
=> Object

> self.methods.include?(:hello2)
=> true

> hello2
=> "hello gem! 2"


require 'my_libs'から後ならMyLibsモジュールが使えるようになっていますね。

これをgem installで使えるようにするために、gemパッケージにします。


Gemをビルドしよう

bundle gemで作った雛形にはgemパッケージ用のタスクが含まれています。


Shell

$ rake -vT

rake build # Build my_libs-0.0.1.gem into the pkg directory.
rake install # Build and install my_libs-0.0.1.gem into system gems.
rake release # Create tag v0.0.1 and build and push my_libs-0.0.1.gem to Rubygems

このうちrake buildがgemファイルを作るタスクです、早速実行してみます。


Shell

$ rake build

my_libs 0.0.1 built to pkg/my_libs-0.0.1.gem.

$ ls pkg/
my_libs-0.0.1.gem


pkg/以下にgemファイルができました。my_libs-0.0.1.gemとバージョン情報が付与されてますね。

試しにバージョンを更新してみましょう、ライブラリは特に変更せず。


my_libs/lib/my_libs/version.rb

module MyLibs

VERSION = "0.0.2"
end

再びrake build


Shell

$ rake build

my_libs 0.0.2 built to pkg/my_libs-0.0.2.gem.
$ ls pkg/
my_libs-0.0.1.gem my_libs-0.0.2.gem

目論見通りmy_libs-0.0.2.gemとなりました。

これでGemファイルが作れるようになったので、配布したいサーバに適当な手段で持っていきましょう。


作ったGemをインストールしよう

ローカルのgemファイルをインストールするには、gem install時に-lオプションでファイル名を指定します。

※ 依存にRubyGemsで公開されているGemがある時は、-b オプションにしましょう。


Shell

$ gem install -l pkg/my_libs-0.0.2.gem -V

Installing gem my_libs-0.0.2
PATH_TO_RUBY/gems/my_libs-0.0.2/.gitignore
PATH_TO_RUBY/gems/my_libs-0.0.2/Gemfile
PATH_TO_RUBY/gems/my_libs-0.0.2/LICENSE.txt
PATH_TO_RUBY/gems/my_libs-0.0.2/README.md
PATH_TO_RUBY/gems/my_libs-0.0.2/Rakefile
PATH_TO_RUBY/gems/my_libs-0.0.2/lib/my_libs.rb
PATH_TO_RUBY/gems/my_libs-0.0.2/lib/my_libs/version.rb
PATH_TO_RUBY/gems/my_libs-0.0.2/my_libs.gemspec
Successfully installed my_libs-0.0.2
1 gem installed

一旦インストールしてしまえばあとは通常のgemsと扱いは変わりません。


Shell

$ gem list | grep my_libs

my_libs (0.0.2)

ついでに実行テストをしてみます。


Shell

$ ruby -e "require 'my_libs'; puts MyLibs.hello"

hello gem!

できましたね。


最後に

一つ注意点として、作成するmodule,classの一番親に来る名前は他と被らないようにしましょう。

これはOKですが、


sample.rb

module MyOriginModule

class File
# hogehogehoge
end
end

この様にド頭に一般名称などを持ってくると他のモジュールとミックスされて、色々と他人がヒドイ目に遭うのでお気をつけて。


sample.rb

class File

# hogehogehoge
end