最近自作フレームワークにrails new
のようなコマンドを追加したくてRubyGemで実行コマンドを作る方法について調べたのでメモしておきます📝
実行コマンドとは?
実行コマンドというのはrails new
やrspec
といった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
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の公式ガイドがあるのしらなかったので時間があるときに読んでみようかなと思いました📚