gemを1個作った事があります。
でも、ネットの情報を寄せ集めて雰囲気で実装していましたが、ファイルの配置などかなりふわふわしたままでした。
## 目的
目的は、元のドキュメントに参照しながらしっかりgemの作ることです。
主に、こちらのHow to create a Ruby gem with Bundlerをみながら、ドキュメントを参照しつつgemを作りました。
環境
$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18]
$ bundle -v
Bundler version 2.1.4
手順
空のgemを作って→機能を実装して→動作確認して→テストコード書いて→readme書いて→githubにpushして→他のプロジェクトから試して →完了
という流れです。
空のgemを作る
まずは、bundlerを使ってgemのひな形を作ります。
今回は、csvを出力するためのgemをつくります。
名前は junara_export_csv
にしました。
$ bundle gem junara_export_csv
Creating gem 'junara_export_csv'...
create junara_export_csv/Gemfile
create junara_export_csv/lib/junara_export_csv.rb
create junara_export_csv/lib/junara_export_csv/version.rb
create junara_export_csv/junara_export_csv.gemspec
create junara_export_csv/Rakefile
create junara_export_csv/README.md
create junara_export_csv/bin/console
create junara_export_csv/bin/setup
create junara_export_csv/.gitignore
create junara_export_csv/.travis.yml
create junara_export_csv/.rspec
create junara_export_csv/spec/spec_helper.rb
create junara_export_csv/spec/junara_export_csv_spec.rb
Initializing git repo in /Users/junara/IdeaProjects/junara_export_csv
Gem 'junara_export_csv' was successfully created. For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html
作ったフォルダに移動します。
$ cd junara_export_csv/
$ pwd
/Users/junara/IdeaProjects/junara_export_csv
なにも作っていませんが、ここでgemのinstallをしてみます。
the install task will build and install the gem to our system (just like it would do if we gem install‘d it)
rake install [master]
rake aborted!
WARNING: See http://guides.rubygems.org/specification-reference/ for help
ERROR: While executing gem ... (Gem::InvalidSpecificationException)
metadata['homepage_uri'] has invalid link: "TODO: Put your gem's website or public repo URL here."
Tasks: TOP => install => build
(See full trace by running task with --trace)
metadata['homepage_uri']
がないといわれます。設定ファイルを記入します。
require_relative 'lib/junara_export_csv/version'
Gem::Specification.new do |spec|
spec.name = "junara_export_csv"
spec.version = JunaraExportCsv::VERSION
spec.authors = ["junara"]
spec.email = ["jun5araki@gmail.com"]
spec.summary = %q{Export CSV for personal.}
spec.description = %q{Export CSV for personal.}
spec.homepage = "https://github.com/junara"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://github.com/junara"
spec.metadata["changelog_uri"] = "https://github.com/junara"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
下記を編集しました。
spec.summary
spec.description
spec.homepage
spec.metadata["source_code_uri"]
spec.metadata["changelog_uri"]
ここれで 再度installします
$ rake install +[master]
junara_export_csv 0.1.0 built to pkg/junara_export_csv-0.1.0.gem.
junara_export_csv (0.1.0) installed.
成功します。 pkg/junara_export_csv-0.1.0.gem
ここにgemが出力されます。
これで最低限のgem 空のgemの作成が終わりました。
機能を実装する
改めて今回作るgemはCSVを出力するgemです。
具体的には、arrayとその処理をblockで渡すとarrayの要素を1行ずつblockで処理してcsv出力する事ができます。
イメージはこんなかんじです
JunaraExportCsv.run(array) {|item| item.[0], item[1], item[2]}
#=> ./2020-03-20_10:00.csv にarrayのitemが出力される
RubyGemsによると gemを読み込んだ時には、 lib
配下のファイルが読み込まれるとあります。
REQUIRING CODE
RubyGems modifies your Ruby load path, which controls how your Ruby code is found by the require statement. When you require a gem, really you’re just placing that gem’s lib directory onto your $LOAD_PATH.
そして、lib直下には1つのファイルが普通とあります。更に複雑なgemを作る場合は複数ファイルに分割する必要があり、その場合は、gemと同じ名前のフォルダ内に複数ファイルを配置します。
The lib directory itself normally contains only one .rb file and a directory with the same name as the gem which contains the rest of the files.
しかし、今回はシンプルなgemなので1ファイルに収まります。よって、 lib/junara_export_csv.rb
に実装を書きます。
# frozen_string_literal: true
require 'junara_export_csv/version'
require 'csv'
module JunaraExportCsv
# usage
# JunaraExportCsv.run([[1, 2, 3], [3, 4, 5]], header: ['1st', '2nd', '3rd']) { |r| [r[0], r[1], r[2]] }
def self.run(records, header: [], filename: nil)
data = read(records, header) { |r| yield(r) }
filename ||= default_filename
export(filename, data)
filename
end
def self.read(records, header)
CSV.generate do |csv|
csv << header if header.is_a?(Array) && !header.empty?
records.each do |r|
csv << yield(r)
end
end
end
def self.export(filename, data)
File.open(filename, 'w') do |f|
f.write(data)
end
end
def self.default_filename
"./#{Time.now}.csv"
end
private_class_method(:default_filename, :export, :read)
end
機能を動かして試してみる
実装した機能を試します。そのため、先ほど実装した機能をインストールします。
bundlerのドキュメントを見ると、 bundle install
とすると this library
がインストールされるとありますのでやってみます。
When we run bundle install, rspec will be installed for this library and any other library we use with Bundler, but not for the system.
$ bundle install
Using rake 12.3.3
Using ast 2.4.0
Using bundler 2.0.2
Using csv 3.1.2
Using diff-lcs 1.3
Using jaro_winkler 1.5.4
Using junara_export_csv 0.1.0 from source at `.`
Using parallel 1.19.1
Using parser 2.7.0.5
Using rainbow 3.0.0
Using rexml 3.2.4
Using rspec-support 3.9.2
Using rspec-core 3.9.1
Using rspec-expectations 3.9.1
Using rspec-mocks 3.9.1
Using rspec 3.9.0
Using ruby-progressbar 1.10.1
Using unicode-display_width 1.6.1
Using rubocop 0.80.1
Bundle complete! 4 Gemfile dependencies, 19 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Using junara_export_csv 0.1.0 from source at
という表示に注目です。bundle installのコマンドの結果、 先ほど作成した機能がinstall されました。
次に コンソールで機能を確かめます。
irbを起動して、
bundle exec irb
junara_export_csv
を読み込み、実行します。
irb(main):004:0> require 'junara_export_csv'
irb(main):004:0> JunaraExportCsv.run([[1, 2, 3], [3, 4, 5]], header: ['1st', '2nd', '3rd']) { |r| [r[0], r[1], r[2]] }
=> "./2020-03-22 23:14:35 +0900.csv"
./2020-03-22 23:14:35 +0900.csv
というファイル名で以下の内容の出力がなされれば正常に動いています。
1st,2nd,3rd
1,2,3
3,4,5
機能のテストを書く
実装した機能のテストコードを書きます。
For this guide, we’re going to use RSpec to test our gem.
bundle gem rspec
で書く例があるので素直にrspecでテストコードを書きます
今回は、 self.run
特異メソッドについてのテストコードを書きました。
# frozen_string_literal: true
require 'tempfile'
RSpec.describe JunaraExportCsv do
it 'has a version number' do
expect(JunaraExportCsv::VERSION).not_to be nil
end
describe '#run' do
let(:subject) do
described_class.run(rows, filename: filename, header: header) { |r| [r[0], r[1], r[2]] }
end
context 'with parameters' do
let(:temp_out_file) { Tempfile.new('csv') }
let(:rows) { [%w[a b c], %w[d e f]] }
let(:filename) { temp_out_file.path }
let(:header) { %w[1st 2nd 3rd] }
after { temp_out_file.unlink }
it 'export filename' do
expect(subject).to eq temp_out_file.path
end
it 'export header' do
subject
lines = CSV.readlines(temp_out_file.path)
expect(lines[0]).to eq header
end
it 'export data' do
subject
lines = CSV.readlines(temp_out_file.path)
expect(lines[1]).to eq rows[0]
expect(lines[2]).to eq rows[1]
end
end
end
end
こちらのコードが通ることをrspecを実行して確認します。
$ bundle exec rspec spec ?[master]
JunaraExportCsv
has a version number
#run
with parameters
export filename
export header
export data
Finished in 0.00749 seconds (files took 0.20855 seconds to load)
4 examples, 0 failures
テストコードが全て成功したことを確認できました。
ReadMeを書く
gemの説明を書きます。 bundle gem
で作成したgemの場合はある程度templateが書かれているので、適宜変更すれば良いです。
すぐに試せる様なusageを書くと、理解しやすいかなーと思うのでそこら辺は丁寧に書きました。
GitHubに公開する
- 普通にpushしてください
使う
githubのソースを指定すれば、bundlerで管理されている他のプロジェクトでも使う事ができます。
The simplest way (from the author’s perspective) to share a gem for other developers’ use is to distribute it in source code form.
具体的には、 https://github.com/junara/junara_export_csv/blob/master/README.md#installation こちらの通りです。
使いたいところのGemfileに下記を追加します。
gem 'junara_export_csv', git: 'git://github.com/junara/junara_export_csv.git'
そしてbundle installすればinstallされます。
$ bundle install
使い方は、 機能を動かして試してみる
もしくは、 https://github.com/junara/junara_export_csv/blob/master/README.md#usage をご覧ください。
その他
これまでの内容で公開し、使う事ができるgemを公開する事ができました。
ただ、sourceをgithubで指定しないといけないのでとても不便です。
一般的なgemは https://rubygems.org/ に公開されます。 https://rubygems.org/ に公開すれば、 gem 'junara_export_csv'
と書くだけでinstallされます。
方法はこちらのページを参照ください。