メモ的な何か

技術的な私のメモになる予定です。

RubyでのCLIアプリケーション開発

はじめに

rubyもなんとなくわかって来たのと開発環境もそこそこ準備が整って来たので、お試しも含めて何か作っていこうと思います。
railsはまだ触ってないのでまずはCLIアプリケーションからと思ってその環境について調べました。
こんな感じを基本構成としようと思ってます。

rubyプロジェクトの作成

rubyプロジェクトフォルダの基本構成はgemの構成に従うのがスタンダードっぽい。
gemの雛形づくりはbundleでできるんだけどそのbundleのrubyバージョンはrbenvが握っているためまずはrbenvでbundleのコマンドを実施する前にバージョンを設定します。

$ rbenv global 2.5.1

もちろんこのバージョンのrubyにbundleが入っている必要があります。

このあとはgemの雛形をつくります。
このときgitの設定でnameとかemailとか設定しておく必要があります。このへんの情報を使うので。ないとどうなるかは試してません。

$ bundle gem sample -b -t
reating gem 'sample'...
Do you want to generate tests with your gem?
Type 'rspec' or 'minitest' to generate those test files now and in the future. rspec/minitest/(none): rspec
Do you want to license your code permissively under the MIT license?
This means that any other developer or company will be legally allowed to use your code for free as long as they admit you created it. You can read more about the MIT license at https://choosealicense.com/licenses/mit. y/(n): y
MIT License enabled in config
Do you want to include a code of conduct in gems you generate?
Codes of conduct can increase contributions to your project by contributors who prefer collaborative, safe spaces. You can read more about the code of conduct at contributor-covenant.org. Having a code of conduct means agreeing to the responsibility of enforcing it, so be sure that you are prepared to do that. Be sure that your email address is specified as a contact in the generated code of conduct so that people know who to contact in case of a violation. For suggestions about how to enforce codes of conduct, see https://bit.ly/coc-enforcement. y/(n): n

-bのオプションは実行ファイルの作成をする、-tのオプションはテストファイルを作成をするになります。
最初だけこんな感じでいろいろ聞かれます。
- テスティングフレームワークrspecとminitestどっち?→rspec(私の回答)
- MITライセンスでいいか?→y(私の回答)
- code of conduct に関するファイルを作成する?→n(私の回答)
Contributor Code of Conduct
code of conductについてはこちらがわかりやすいです。

プロジェクトの雛形として以下のファイルが作成されます。

create  sample/Gemfile
create  sample/lib/sample.rb
create  sample/lib/sample/version.rb
create  sample/sample.gemspec
create  sample/Rakefile
create  sample/README.md
create  sample/bin/console
create  sample/bin/setup
create  sample/.gitignore
create  sample/.travis.yml
create  sample/.rspec
create  sample/spec/spec_helper.rb
create  sample/spec/sample_spec.rb
create  sample/LICENSE.txt
create  sample/exe/sample

更にプロジェクトのrubyのバージョンを固定するために以下をしておきます。(あまり強制力はないです。)

$ cd sample/
$ rbenv local 2.5.1

最後にbundle installとかするときにエラーとならないようにsample.gemspecを修正しておきます。 TODOがあるとエラーになります。

- 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."
+ spec.summary       = "sample application"
+ spec.description   = "sample application"
+ spec.homepage      = "https://github.com/ruihub/"

ちなみにhomepageに適当な文字列いれたらだめでした。どこまでかわからないですが、存在するURLをいれておくのが無難です。

CLIアプリケーションの作成

CLIアプリケーションにはThorというgemを使います。
gemの追加に関してはsample.gemspecにgemを追記します。

  spec.add_development_dependency "bundler", "~> 1.16"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"

+ spec.add_dependency "thor"

これで後ほどのgemコマンドでthorが追加されます。うしろに「, "-> バージョン"」をつければバージョンも固定できます。
developmentがついているの開発時のみにしか使わないgemです。

次にCLIクラスを作成します。 参考先に従ってlib/パッケージ名/cli.rbとしました。 ThorではThorを継承したクラスに宣言したpubulicメソッドがコマンドとなるようです。
メソッド上部にdescで"コマンドの使い方","コマンド説明"を記載するこでhelpコマンドでその内容が確認できます。

  require "sample"
  require "thor"
  
  module Sample 
    class Cli < Thor
      desc "hello {name}", "Hello {name}!"
      def hello(name)
        puts "Hello #{name}!"
      end
    end
  end

続いてlib/パッケージ名.rbにcli.rbをrequireするよう修正します。
実行ファイルから呼び出されるファイルがこのファイルになります。

  require "sample/version"
+ require "sample/cli"
  
  module Sample
    # Your code goes here...
  end

実行ファイルはこれまた参考の更に参考先の意見をもとにexe/以下に配置することにしました。

  #!/usr/bin/env ruby

  require "sample"

+ Sample::Cli.start

アプリケーションの実行

まずはbunde installを実行してThor含め必要なgemをとってきます。
ここで忘れてはいけないのが今回に限った話ではないけどこのままbunde installを実行してしまうとグローバルにgemをインストールしてしまうので、プロジェクトフォルダ以下に配置するようにオプション --path ディレクトリ をつけてプロジェクトディレクトリ配下の指定のディレクトリにgemをインストールします。 ディレクトリはvendor/bundleとするのが一般的なようです。

$ bundle install --path vendor/bundle
$ ls -l
total 48
-rw-r--r--  1 rui  staff   161  7 10 21:33 Gemfile
-rw-r--r--  1 rui  staff   651  7 11 20:11 Gemfile.lock
-rw-r--r--  1 rui  staff  1073  7 10 21:33 LICENSE.txt
-rw-r--r--  1 rui  staff  1324  7 10 21:33 README.md
-rw-r--r--  1 rui  staff   117  7 10 21:33 Rakefile
drwxr-xr-x  4 rui  staff   128  7 10 21:33 bin
drwxr-xr-x  3 rui  staff    96  7 11 20:10 exe
drwxr-xr-x  4 rui  staff   128  7 11 19:59 lib
-rw-r--r--  1 rui  staff  1545  7 10 22:22 sample.gemspec
drwxr-xr-x  4 rui  staff   128  7 10 21:33 spec
drwxr-xr-x  3 rui  staff    96  7 11 20:11 vendor

その後は以下でコマンド一覧の確認

$ bundle exec exe/sample
Commands:
  sample hello {name}    # Hello {name}!
  sample help [COMMAND]  # Describe available commands or one specific command

ヘルプの参照

$ bundle exec exe/sample help hello
Usage:
  sample hello {name}

Hello {name}!

実装したhelloコマンドの実行

$bundle exec exe/sample hello Ruby
Hello Ruby!

という感じでThorを使うことによってCLIアプリケーションが簡単に作成できました!

参考

qiita.com