Gemを初めて作ってRubyGemsで公開したので、作業メモと感想をまとめてみた。
作ったGemはなんてことはないもので、ActionMailerのメール送信先を強制的に変更するもの。開発時に飛ばすメールを全部自分の手元に飛ばすために作った。
Gemの作り方
Gem作成コマンド
RailsにもRailsプラグインがあり、そちらでもGemのスケルトンを作れるみたいだけど、Raisl用だろうと普通のGemだろうと、bundleコマンドで作るのが良いと思う。
$ bundle gem newgem -t
なお、Railsプラグインの作り方は以下のコマンド。作成される物の構成は大きく変わらない。
$ ./bin/rails plugin new newplugin
Gemの初期設定
hoge.gemspec
というファイルがあり、それがGemの設定ファイル。
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'newgem/version'
Gem::Specification.new do |spec|
spec.name = "newgem"
spec.version = Splug::VERSION
spec.authors = ["zaru@sakuraba"]
spec.email = ["user@example.com"]
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."
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
# delete this section to allow pushing this gem to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
else
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
end
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec"
end
TODOと書かれている所を埋めていくと良い。具体的には以下の3つ。homepageにはGitHubのリポジトリを指定しておけばOK。全て英語で書く。
- spec.summary
- spec.description
- spec.homepage
もし今から作ろうとしているGemは非公開、プライベートなGemだ!っていう場合は、spec.metadata['allowed_push_host']
にpushしてもよいホストを指定しておこう。誤操作で公開してしまうことを防ぐことが出来る。そうじゃなくて、全世界に公開だ!という場合は、if spec.respond_to?
の下りから全部消しても構わない。
Gemのデバッグ方法
普通にRspecでテストが書けるので、普通にテストすれば良い。
$ bundle exec rspec
Gemを組み込んで動作テストしたい
作ったGemをとりあえずテスト的に導入したいときがあります。その場合は、すでに編集したファイルをコミット済みの上で、以下のコマンドを実行するとローカルにインストールされます。
$ bundle exec rake install
使って見るにはrequire
で呼び出せばOKです。なぜかpry環境下だと読みこむことが出来なかったので、irbで試しています。
$ irb
> require `newgem`
GemをRubyGemsに公開する
動作テストも終わり、いよいよ公開したいということになりました。まずは、RubyGems.orgにアクセスしユーザ登録をします。簡単です。そして、マイページにアクセスをして、設定ファイルのダウンロードコマンドをゲットします。
$ curl -u zaru https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
こんなやつ。
そしたらいよいよリリースする。
$ bundle exec rake release
RubyGemsのGemを更新したい
何らかのバグ解消や新機能の追加でRubyGemsに公開したGemを更新したいという時には、Gemのバージョンを上げる必要がある。
module Splug
VERSION = "0.1.0" # ここのバージョンを変更する
end
あとはコミットしてプッシュしてからのrake release
コマンドで完了。簡単ですね。
Gem独自の設定ファイルを作りたい
Gem自身にはデフォルトの設定があり、利用者側がそれを上書きできるような設定ファイルが欲しい。よくあるやつです。こんな時にもActiveSupportが強力な味方になってくれる。
require 'active_support/configurable'
module Newgem
def self.configure(&block)
yield @config ||= Newgem::Configuration.new
end
def self.config
@config
end
class Configuration
include ActiveSupport::Configurable
config_accessor :hoge_configure
end
configure do |config|
config.hoge_configure = "hoge"
end
end
active_support/configurable
を使うことで簡単に設定ファイルの下準備が可能になる。この例だとhoge_configure
という設定キーを作り、Gem上ではデフォルトhoge
が指定されている。要はブロックを渡して中身を上書きする感じ。
require "newgem/version"
require "newgem/config"
module Newgem
class Newgem
def example
p Newgem.config.hoge_configure
end
end
end
Gem内部から設定値を使用するにはNewgem.config.hoge
といった形で呼び出すことが出来る。
利用者側
Rails環境下の例になるが、こんな感じで上書き設定が可能になる。
Newgem.configure do |config|
config.hoge_configure = 'piyo'
end
Gemを作ってみて
今回作ったのはRailsに付属しているActionMailerのサンドボックス化するGemで、中身は単純にモンキーパッチでしかなく、モンキーパッチならGemじゃなくて良いじゃんとか思ったんだけど、プロジェクト作るたびにモンキーパッチ書いてたら面倒だなーと思ってGemにしてみた。この作法がGem界隈で正しいのかは知らない。
でもGemにして公開したことで同僚に簡単に勧められるようになったし良かったと思っている。Gem作成の第一歩としては、とても小さくて踏みやすい一歩。作ってみると思っていた以上に簡単だったし、公開自体もなんのことはない感じ。
無駄にGemを作る意味はないけど、なんらかの目的や役割が果たせるのなら、ガンガン作っていっていくと良いような気がした。