今更ながらRuby について真剣にやり直そうと思う。理由はまぁ色々有るのだけど。。。どうもRuby は苦手だ。
さて、gem を作る。今までとりあえずgem install していたけど、gem ってそもそもどうなっているんだろうか??
bundle gem gemname
これで雛形を生成することが出来る。おそらくデフォルトのままで問題ないと思う。生成されるgem のファイル構成は以下のようになっている。
├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin │ ├── console │ └── setup ├── lib │ ├── testgem │ │ └── version.rb │ └── testgem.rb ├── spec │ ├── spec_helper.rb │ └── testgem_spec.rb └── testgem.gemspec 4 directories, 12 files
testgem と言うのは私が書いた名前なので、各自の環境で変えていただきたい。ruby でrequire が呼ばれた時、このlig/testgem.rb が呼ばれる。また、このgem を呼び出すにはどうしたら良いのか。
このディレクトリとは別に、'callgem'というディレクトリを作成し、Gemfile を作成する。ローカルのgem を呼び出す時は、path属性を指定してあげる。具体的には以下のようになる。
gem 'testgem', :path => '../testgem'
さて、これでbundle install
しようとするとエラーが起こる。どうやらspec ファイルがまだvalid じゃない(テストが通ってない)と言われるので、コレをアレコレ書く所から始めようと思う。
早速gemspec ファイルを開けるよく見ると中にToDo という文字列が見つかるので、そのへんを適当に改良する。以下のようになった。
# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'testgem/version' Gem::Specification.new do |spec| spec.name = "testgem" spec.version = Testgem::VERSION spec.authors = ["bussorenre laboratory"] spec.email = ["mailaddress@bussorenre.com"] spec.summary = %q{おためしで作ったgem} spec.description = %q{こんなんでいいのか} spec.homepage = "http://localhost:3000" spec.license = "MIT" # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' # to allow pushing to a single host or delete this section to allow pushing to any host. if spec.respond_to?(:metadata) spec.metadata['allowed_push_host'] = "'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 do |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"] # ココに依存しているgem を追加する spec.add_development_dependency "bundler", "~> 1.14" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rspec", "~> 3.0" end
本当にToDO のところを書き換えただけです。
さて、肝心のこのgem ですが、ping というメソッドを実装し、呼び出されたらpong と返す。たったそれだけのgemを作成します。
まずspec
require "spec_helper" RSpec.describe Testgem do it "has a version number" do expect(Testgem::VERSION).not_to be nil end it "response pong if ping" do expect(Testgem.Ping).to eq('pong') end end
実装
module Testgem def self.Ping 'pong' end end
これで、rspec が通った! というわけで、さっき作ったcallgem から呼び出してみる。
まずはbundle install
する。すると問題なくbundle install 出来たので、コードを書く。
require 'testgem' puts Testgem.Ping
これをbundle exec ruby main.rb
で実行すると、無事pong と表示される。
結論
gem が出来た。所謂有名所のgem も基本はこういう原理になっているはずなので、コードリーディング等に役立てていきたい。