Madogiwa Blog

主に技術系の学習メモに使っていきます。

自作RubyGemで実行コマンドを作る方法

最近自作フレームワークrails newのようなコマンドを追加したくてRubyGemで実行コマンドを作る方法について調べたのでメモしておきます📝

github.com

実行コマンドとは?

実行コマンドというのはrails newrspecといったRubyのコード外からgemのコードを呼び出すようなものです。

Railsではrailtieと呼ばれるgemで提供されている機能ですね。

rails/railties at master · rails/rails · GitHub

実行コマンドの作り方

実行コマンドを作成するには、rubygemsのリファレンスマニュアルを見てみると下記のように設定すれば良いと書かれています。

Gem::Specification.new do |s|
  s.name              = 'hello'
  s.version           = '0.0.0'
  s.summary           = 'hello summary'
  s.files             = ['bin/hello', 'lib/hello.rb']
  s.executables       = ['hello']
  s.authors           = ['Hello Author']
  s.email             = 'hello@example.com'
  s.homepage          = 'http://example.com/hello'
  s.rubyforge_project = 'hello'
  s.description       = 'hello description'
end

docs.ruby-lang.org

rubygemの公式ガイドを見ると上記の設定のなかのexecutablesに実行コマンドを定義してあげれば良いようです。

Executables included in the gem. For example, the rake gem has rake as an executable. You don’t specify the full path (as in bin/rake); https://guides.rubygems.org/specification-reference/#executables

またるりまには記載されていませんが実行形式のファイルは、bindirオプションで指定したパスに配置されることが望ましいようです。

all application-style files are expected to be found in bindir. https://guides.rubygems.org/specification-reference/#executables

bindirは、実行可能なスクリプトを配置ディレクトリを指定するコマンドです。

The path in the gem for executable scripts. Usually 'bin' https://guides.rubygems.org/specification-reference/#bindir

そのため、実際はこのような形式になりそうですね👀

Gem::Specification.new do |s|
  s.name              = 'hello'
  s.version           = '0.0.0'
  s.summary           = 'hello summary'
  s.files             = ['bin/hello', 'lib/hello.rb']
  s.executables       = ['hello']
  s.executables       = ['bin']
  s.authors           = ['Hello Author']
  s.email             = 'hello@example.com'
  s.homepage          = 'http://example.com/hello'
  s.rubyforge_project = 'hello'
  s.description       = 'hello description'
end

実行コマンドをつくる

実際にgem内に実行コマンドを作るのは普通のRubyスクリプトを書くのと同じです。

#!/usr/bin/env ruby

require 'hello/version'

if ARGV[0] == '-v'
  puts Hello::VERSION.to_s
end

試すときは普通にRubyで実行してあげるだけです。

$ ruby exe/hello

下記は参考までに定義しておいたRakeタスクを実行するコマンドを作成する例です。

#!/usr/bin/env ruby

require 'makanai'
require 'makanai/rake_tasks'

if ARGV[0] == 'init'
  Rake::Task['makanai:initialize:app'].execute
end

実行コマンドを試す

実際に実行コマンドを作成したgemをリリース前にインストールして試す方法を書いときます。

手順としてはローカルにgemをビルドして、作成したパッケージをgem installで取り込みます。

$ bundle exec rake build
$ gem install pkg/hello-0.0.0.gem

これでhelloコマンドが使えるようになりました🙌

※実際にbundle gemを作ったときにgemspecを見ると下記のようになっていたgit管理下に置かれていないファイルはビルド対象に含まれません。 事前にcommit等を行いgit管理下においた上でbundle exec rake buildを実行しましょう。

  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) }

おわりに

rubygemで実行コマンドを提供できるので、CLIツールとか簡単に公開できて良いですね💻
それとrubygemの公式ガイドがあるのしらなかったので時間があるときに読んでみようかなと思いました📚

参考

docs.ruby-lang.org

guides.rubygems.org

qiita.com