はじめに
rubyのgemはthorを利用することで簡単にコマンドを作成することができる. コマンドをつける目的としては, なんらかの操作(APIを叩く,ファイル生成など)を自動化するというものが多いだろう.
そういった操作には, しばしば入力が必要となるが, 毎回同じ入力をするのは非常にめんどくさい.
そこで, 入力する情報や設定を保存し, それを利用する方法について書く. 具体的には, configコマンドを作成し, 設定を保存するとともに, 他のコマンドからその情報を利用してみる.
最終的にできあがるものは, 以下のようなものである.
$ bundle exec mygem config
Input your name: User name # User nameを入力
Update Your name to [User name].
$ bundle exec mygem hello
Hello!, User name # 保存したデータを利用する
準備: gemの作成とhelloコマンドの作成
gemの準備
まずは、bundlerを利用してgemを作成する。
$ bundle gem mygem
$ cd mygem
mygem.gemspecのTODOとなっているところを編集する。また、thorをインクルードしておく。
.
.
spec.summary = %q{mygem}
spec.description = %q{mygem}
spec.homepage = "#githubのレポジトリなど"
.
.
# thorを依存gemに追加
spec.add_dependency "thor"
end
helloコマンドの作成
thorについて詳しくない方のために,
本題に入る前にHello!と出力するだけのhelloコマンドを作ってみる.
以下のようにファイルを準備する.
require 'mygem'
require 'mygem/command'
module Mygem
class Command < Thor
desc 'hello', 'say Hello!'
def hello
puts "Hello!"
end
end
end
require 'mygem'
require 'thor'
require 'mygem/command/hello'
module Mygem
class Command < Thor
end
end
require "mygem/version"
require "mygem/command"
module Mygem
end
gemの実行ファイルを作成する.
require 'mygem'
Mygem::Command.start
ビルド&インストール&実行する.
$ git add -A .
$ git commit -m 'init'
$ rake build
$ rake install
$ bundle install
$ bundle exec myconfig
Commands:
mygem hello # Say Hello!
mygem help [COMMAND] # Describe available commands or one specific command
$ bundle exec mygem hello
Hello!
これでmygemにhelloコマンドが追加された.
本題: configコマンドの作成と実行
今回は,データの保存先をホームディレクトリ直下の, gem名の隠しディレクトリ以下とする.
つまり, ~/.mygem/settings.yml である.
ヘルパーメソッドの作成
さて, configコマンドを作成するに当たり, やりたいことは以下の3つである.
- コンフィグを設定する
- コンフィグを保存する
- コンフィグを取得する
settings.ymlに対して上の3つを行うヘルパーメソッドを以下のように作成する.
require 'fileutils'
require 'yaml'
require 'psych'
module Mygem
# Configuration defaults
@config = {
name: 'default'
}
@valid_config_keys = @config.keys
# Configure through hash
def self.configure(opts = {})
self.config
opts.each do |k, v|
@config[k.to_sym] = v if @valid_config_keys.include? k.to_sym
end
self.save_config
end
def self.get_config_path
config_path = Dir.home + '/.mygem'
if Dir.exists?(config_path)
# use user settings
config_path
else
raise "Can't find config directory. please init by command: 'mygem config'.'"
end
end
# configをyamlから@cofigに取得
def self.config
yml_path = get_config_path + '/settings.yml'
yml_file = YAML.load_file(yml_path)
if yml_file
@config = yml_file
else
File.open(yml_path, 'w') { |f| YAML.dump(@config, f) }
end
end
# 現在の@configをyamlに保存
def self.save_config
yml_path = get_config_path + '/settings.yml'
if File.exists?(yml_path)
File.open(yml_path, 'w') { |f| YAML.dump(@config, f) }
else
raise "Can't find #{yml_path}. please set configure."
end
end
end
require 'fileutils'
require 'yaml'
require 'psych'
require "mygem/version"
require "mygem/command"
require 'mygem/helper/config_helper' # 追加
module Mygem
end
config_helperでは, Mygem.configure(name: 'name')とした後で, save_configで現在のconfigをyamlに保存する.
そして, データが保存してあれば Myconfig.config[:name] でデータが取り出せるようになる.
configコマンドの作成
configの設定, 保存, 参照ができるようになったので, いよいよconfigコマンドを作成する.
configコマンドでやることは, 以下の3つである.
- 初回起動時に設定ファイルを作成
- 入力を受け付ける
- 入力を設定として保存する
これを以下のように実装する.
require 'mygem'
require 'mygem/command'
module Mygem
class Command < Thor
desc 'config', 'change settings'
def config
# 初回起動時に設定ファイルを作成
config_path = Dir.home + '/.mygem'
if Dir.exists?(config_path)
puts "Your current name is [#{Mygem.config[:name]}]."
else
Dir.mkdir(config_path)
yml_path = Mygem.get_config_path + '/settings.yml '
File.open(yml_path, 'w').close
end
# 入力を受け付ける
print 'Input your name: '
loop do
s = $stdin.gets.chomp!
if s.size != 0
# 設定を更新
Mygem.configure(name: s)
break
else
puts 'Invalid Name. please try again:'
end
end
puts "Update Your name to [#{Mygem.config[:name]}]."
end
end
end
require 'myconfig'
require 'thor'
require 'myconfig/command/hello'
require 'myconfig/command/config' # 追加
module Myconfig
class Command < Thor
end
end
設定を利用する
これで自由にnameを設定できるようになったので, 最後にhelloを更新して設定を利用するようにする.
require 'mygem'
require 'mygem/command'
module Mygem
class Command < Thor
desc 'hello', 'call your name and say Hello!'
def hello
puts "Hello, #{Mygem.config[:name]}!"
end
end
end
以上で完成したので, ビルド&インストールして使ってみる.
$ rake build; rake install
$ bundle install
$ bundle exec mygem
Commands:
mygem config # Change settings
mygem hello # Call your name and say Hello!
mygem help [COMMAND] # Describe available commands or one specific command
$ bundle exec mygem hello
# 設定をしていないのでエラーが表示される
$ bundle exec mygem config
Input your name: Myname
Update Your name to [Myname].
$ bundle exec mygem hello
Hello!, Myname
$ bundle exec mygem config
Your current name is [Myname]. # 現在の設定が表示される
Input your name: New Name
Update Your name to [New Name]. # 設定を更新
$ bundle exec mygem hello
Hello!, New Name # 新しい名前が表示される
保存されているファイルを見てみると, 以下のように保存されている.
---
:name: New Name
おわり
参考
今回作成したgem
https://github.com/keigo-brook/gem_myconfig