Ruby2.4のoptparseでHashにパース結果をマッピングするintoという便利オプションを調べた
表題の通りなんですが
上記のページの「Parse CLI options into a Hash」の項目を見ると、以下のように parse
メソッドに :into
でハッシュオブジェクトを渡すと自動でマッピングしてくれるという地味に便利な機能が追加された。
上記のURLから抜粋
require 'optparse' require 'optparse/date' require 'optparse/uri' cli = OptionParser.new do |options| options.define '--from=DATE', Date options.define '--url=ENDPOINT', URI options.define '--names=LIST', Array end config = {} args = %w[ --from 2016-02-03 --url https://blog.blockscore.com/ --names John,Daniel,Delmer ] cli.parse(args, into: config) config.keys # => [:from, :url, :names] config[:from] # => #<Date: 2016-02-03 ((2457422j,0s,0n),+0s,2299161j)> config[:url] # => #<URI::HTTPS https://blog.blockscore.com/> config[:names] # => ["John", "Daniel", "Delmer"]
:into
で便利になるのはわかるものの、このサンプルを見ると define
って何だろう、とか短いオプション名(-u
とか)も指定した場合どうなるの?ってところが色々と疑問だったので調べてみた。
define is 何
情弱なのでリファレンスマニュアルに載ってないAPIだから define
を使ったオプションの定義したことがなかった(実は載っているのかと思ってドキドキしたけどやっぱり載ってない)。
というわけでRubyのソースを確認して見るとこんな感じ
https://github.com/ruby/ruby/blob/v2_4_2/lib/optparse.rb#L1465-L1505
抜粋すると以下のように、いつも使っている on
メソッドが内部で呼び出しているメソッドなんですね。
def define(*opts, &block) top.append(*(sw = make_switch(opts, block))) sw[0] end def on(*opts, &block) define(*opts, &block) self end
ソース内の雰囲気からすると、 on
は公開用で define
は内部で使う用っぽい気がするけど*1、普通に呼び出せるしどっちでも良いのかもしれない。まあ、今まで通り on
系を使えば良いかなって気がしますね……。
オプション名 is 何
割り当てるオプション名ってどう決まるのか。
options.on '-a, '--argument=VAL'
みたいに定義した時にどっちが使われるのかなという話でもありますし、オプション名に -
が含まれていた場合どうなるのか(ネタバレすると:"foo-bar"
みたいになる)など疑問が湧きますよね。
これを知るにはざっくり :into
オプションの流れを追う必要があるのですが、結論を先に書いておくと
- 短いオプション名と長いオプション名があった場合長いオプション名が使用される
- オプション名の先頭ハイフンを取り除いた文字列を
.to_sym
した値になる
という動作のようです。
プログラム的には
- ここで
:into
があった場合の動作が定義されていて、オプション名を.to_sym
している - ハッシュの名前としては
switch_name
の値が使われて switch_name
は長い名前を優先して使用する
という流れのようですね。
まとめ
OptionParser.new do |options| options.on '-r', '--ruby=VAL' do |val| val.downcase end options.on '-p', '--perl=VAL' do |val| val.upcase end options.on '-g', '--go-lang' do 'go' end options.on '-d' do true end options.on_tail '-h', '--help', 'hi' end
こんな定義をした場合、 into
オプションでHashを渡した場合は
{ ruby: 'ruby', perl: 'PERL', 'go-lang': 'go', d: true }
こんな値が得られます。便利ですね。
サンプルソースコードとテストケースは以下にあります(主に test/unit
を使ってみたかっただけw)。
https://github.com/sugamasao/optparser_ruby24_into_sample
*1:実際のところはどうなんでしょうか?
3DS LLがWifiを見つけられなくなった(解決済み→ではなかった)
ある日気がつくとインターネットに繋がらなくなった
我が家の環境は以下のような流れで接続している(細かくいうともうちょっとあるけど)
- 各機器
- AirMac (https://www.apple.com/jp/airmac-express/)
- インターネット
そして、他の機器は問題なく接続できているにも関わらず、3DSだけ、ある日突然繋がらなくなった。
具体的にいうと、アクセスポイントを見つけることが不可能になってしまい、結果としてインターネットに繋がらなくなった。
2年くらい前にも同じ現象が発生したが、気がついたら解消していた。だがしかし、また発生してしまった。普段インターネットに接続することはないけど、ゲームを購入するときにダウンロードで購入できないのは困る。
具体的には👇の発売日までにはどうにかする必要があって、すわ修理や買い替えが必要か!と思ったけど、自力で解決できた。
対応方法
まず、Wifi側の再起動や3DS本体の再起動、3DSについてるWifiのスイッチなどは何度かON/OFFを試したが効果はなかった。 何度やっても「アクセスポイントが見つかりませんでした」と表示される。
3DS側のインターネット接続を見直す
3DSのインターネット接続で、新規登録→アクセスポイントを検索でも上記と同じ結果。 その他、手動でSSIDやセキュリティを入力する方式で試してもアクセスポイントが見つからない状態は変わらない*1。
必死にググっていたところ、検索結果のうちの一つに、接続先の詳細設定でIPアドレスなどを手動で入力すると繋がったという情報が載っていたのを発見した。
モノは試しということで、 IPアドレス
と DSN
を手動で設定したところ、無事にインターネットに繋がるようになった。
なぜ自動取得だとうまくいかないのかはよくわからないのだけど、ハード的にWifi部分がぶっ壊れているとかではなくてよかった。
設定メモ
繋がるようになった3DSのネットワーク設定をメモしておく
- Wifiルーター : Air Mac
- SSID : 自分のWifiルーターのやつ
- セキュリティ :
WPA2-PSK(AES)
- IPアドレス(詳細設定)
- DNSの設定(詳細設定)
- Proxyの設定 :
使用しない
(デフォルト) - MTU値 :
1400
(デフォルト)
繋がるようになったことで、ファイアーエムブレム Echoesの無料コンテンツが届いていることに気がつけてとてもお得でした。
ファイアーエムブレム Echoes もうひとりの英雄王 |オンラインコード版
- 出版社/メーカー: 任天堂
- 発売日: 2017/04/19
- メディア: Software Download
- この商品を含むブログを見る
追記:なんか明らかに繋がっていたのだが、数分後にはアクセスポイントが見つかりません状態に戻ってしまった。あれは一体何だったんだ……
*1:ここまでは今まで何度も試したが解決しなかった
エラスティックリーダーシップを読んだ
読んだと言うかもちろん読んだのですが訳者の島田( @snoozer05 )さんからご恵贈いただきました(ありがとうございます!!)。
- 作者: Roy Osherove,島田浩二
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/05/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
ちょっとずつ読み進めていましたが、先日、ようやく読み終えました*1。
あまりリーダー向けの本などを読んだことがなったので、なんとなく「こうやったほうが良さそうだなぁ」と雰囲気で思っていたことに対して名前がつけられていたり、かなり具体的に書かれているのがとてもよかった*2。
以下は印象に残った部分について簡単に書いた内容です。
6章 コミットメント言語
章自体の趣旨としては、章のタイトル通りミーティングなどでこれからやることを決めた際に、タスクとしては上がっているにも関わらず「なる早で対応します〜」のような期日や成果に対してふんわりとした言い方をせずに、具体的な言い方をしましょうという話です。
コミットメント言語でやることを明確にしましょうと言われれば「そりゃそうだ」と思う反面、予定外のものや想定以上の問題があったりして簡単にコミットできないよねというのもまた事実ですよね。ではどうすれば良いのか?ということが具体的に述べられていて、例えば、「来週中にバグを直します」ではなく、「来週は毎日5時間バグを修正するために使います」のように、自分が制御できる内容に落とし込んでコミットしましょうということが書いてあって、とてもよかった。
何が良いって、これ、上っ面だけ読んで「〜します」と言わせるようにした結果「なんでできないんだ」とならないように現実に即している内容が書いてあるのが良いです。
8章 クリアリングミーティング
恥ずかしながらこのような言葉を知らなかった。 本文中の定義を引用すると、以下のようなこと(本ではもっと詳しく書いてあるよ!)。
クリアリングミーティグと呼ぶ理由は、うまくいっていないこと、仕事についてしまいこんでいる悪い感情、共有すべき情報など、チームが知っていること全てを明らか(クリア)にするからだ。そして、それに対処する。
具体的にどういうことをやり取りするかはぜひ本書を手に取ってもらうとして、うまくいっていないことを引き出し方や話を終わらせるポイントなどが載っていて、やっぱりこれも単にやり方だけあって「ギスギスしちゃう・・・」みたいにならないようなケアがされてるのがとても良い。
そのほか
後半の第4部、第5部は色々な人のリーダーシップに関するエッセイになっているのだけど、第5部は国内の著名なエンジニアによるエッセイになっている。国内のエンジニアのエッセイになるとグッと身近な感じが*3してきて、刺激的だったりする。
エラスティックリーダーシップを少しずつ読んでたのだけど、40章リーダーシップは誰のためのものかというエッセイがすごく良い……もちろん、他の部分にもたくさん良いこと書いてあるんだけど
— でも幸せなら🆗です (@sugamasao) 2017年6月24日
総じて、あまり知らなかったり、自分の中で明文化されていないような考え方が非常に具体的に*4載っているのがよかったと思う。 多分、ふだんチームメンバーを抱えているリーダーだけではなく、ミーティングでファリシテーションするような人とかが読んでも有用だと思う。もちろん、メンバーという立場でも自分から発言する形を見直していくというのもすごく良いと思う。
とにかく、語彙がなくて良かったしか書けないけどこういう内容はなかなか見ない種類の本だったのでとにかくよかった。
- 作者: Roy Osherove,島田浩二
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/05/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
どうしても書かなくてはいけない宣伝
先日発売した改訂2版パーフェクトRubyですが、なんとKindle版も発売しているのでよろしくお願いいたします(下の方がkindle版です)。
- 作者: Rubyサポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2017/05/17
- メディア: 大型本
- この商品を含むブログ (1件) を見る
- 作者: Rubyサポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2017/05/17
- メディア: Kindle版
- この商品を含むブログを見る
今回はちゃんとリフロー型になっているので、お使いのデバイスでもおよそ見やすい形になっていると思います。 もちろん、gihyo.jpからであればEPUB/PDFのどちらも購入することが可能です。
本日(5/17)改訂2版 パーフェクトRubyが発売されます
パーフェクトRubyの改訂をしていました
既に技術評論社さんのサイトやAmazonにも載っているのでご存知の方も多いかもしれませんが、最近はパーフェクトRubyの改訂をしていました。
目次などの詳しい情報はgihyo.jpの公式サイトをご覧ください。
書籍版はAmazonでも購入できます。ついうっかり初版を買わない様に注意してください(ヒント:今回のモチーフは鳥です)。
ところで私は見本誌を送付してもらう住所を書き間違えて不達になってしまったため、未だに見本誌が手元にありません😇
初版持ってるんだけど違いはあるの?
いろいろ誤字やなんとも言えないサンプルコードなどを直しているので書籍としてのクオリティは上がってると思うのですが、内容的に大きく変わったところを簡単に書くとこんな感じです
- Ruby 1.9時代などに使われた旧時代の便利テクなどは控えめです
- 初版で対応していたRuby 2.0以降(もちろん2.3, 2.4も)で追加されたメソッドなどにも可能な限り対応しています
- 元々Sinatraを紹介していた章をtest-unitの章に置き換えました
- capistranoには消えてもらいました*1
テストとsinatraにまつわるお気持ちの供養(ただのポエムです)
「パーフェクトRubyはテストがあればパーフェクトなのに」誰だってそー思う。俺だってそー思う。本当にそうだと思うのですが、実は初版の執筆時点ではテストの章はあったんですよね。
15章のツールに対してRSpecでテストを書くというのをやっていたのですが、紙面の都合で泣く泣く削ってしまったのです。
また、当時はシリーズとしてパーフェクトRuby on Railsが無かったため、Rubyの書籍としてWebアプリに関する説明がほぼ無いのはどうなのだ、という懸念があってWebアプリの習作としてSinatraを採用しました。まぁここら辺は私の趣味なんですけどね。
という経緯から数年経ち、Ruby標準で付いてくるテスティングフレームワークも落ち着いた*2*3のもあり、Webアプリに関することはパRailsに任せれば良いかなというところで今回の構成になったのでした。
電子書籍について
gihyo.jpからのPDFなら今すぐ買えます!!!
Amazonでの販売についてはしばしお待ちください😅
RSpecで遅いテストを見つける
--profile
オプションを使う
普段きちんとRSpecを使っている人にとっては常識なのかもしれません。というか普通にhelpに載っているので常識なのでしょう、、、。
RSpecで遅いテストを見つけるには、--profile
オプションを使うと簡単に見つけることができます。
% bundle exec rspec --profile 3 .................................. Top 3 slowest examples (4.24 seconds, 61.5% of total time): Pooka Pooka::Master Worker#run worker received usr1 signal(signal_handler_thread Error) 1.41 seconds ./spec/pooka_spec.rb:86 Pooka Pooka::Master worker received hup signal(fail config reload) 1.41 seconds ./spec/pooka_spec.rb:109 Pooka Pooka::Master Worker#run worker received hup signal 1.41 seconds ./spec/pooka_spec.rb:53 Top 3 slowest example groups: Pooka 0.76258 seconds average (6.86 seconds / 9 examples) ./spec/pooka_spec.rb:3 Pooka::Configuration 0.00121 seconds average (0.01575 seconds / 13 examples) ./spec/pooka/configuration_spec.rb:5 Pooka::PID 0.00063 seconds average (0.00443 seconds / 7 examples) ./spec/pooka/pid_spec.rb:4 Finished in 6.89 seconds (files took 0.24356 seconds to load) 34 examples, 0 failures
--profile
の後に数値を指定することで出力する件数を調整することもできます。
macOS Sierra時代のsyslogとの付き合いかた
/var/log/system.log
へ書き込まれないのでした
ある調査によると、人間は一日におよそ86400回はsyslogに出力したいと願っているそうです*1。
さて例えばlogger
コマンドを使って syslog に出力しておく、なんていうことは稀によくあることではないでしょうか。私は稀によくあります。
ところが、MacにおいてSierraにアップグレードしてからというもの、loggerコマンドや何がしかのプログラミング言語を使ったsyslogへの出力を行なってもsyslogーーいわゆる /var/log/system.log
へ書き込まれないのでした。
統合されたログ環境
実は macOS Sierra 10.12 あたりを見ると、なんとなくsyslogについて言及されている。
要約すると
- ASL (Apple System Logger)という統合されたログ環境になったよ
- 見るなら Console.app を見てね
- log コマンドでも見れるよ
そんなわけで、loggerコマンドなどで出力したログは虚空に吸い込まれたわけではなく、ASLに出力されているのでした。
ログを検索することもできる
新しくなったconsole.appで logger プロセスからの出力でフィルタリングしつつ、loggerコマンドを実行するとこんな感じで出力される。
もちろん、過去に出力されたログを検索することもできる。
また、上記で書いたように log
というコマンドも用意されていて*2、それを使うと、例えばこんな風にログを検索することもできる。
% log show --style syslog --predicate 'processImagePath endswith "logger"' --start "2017-04-06 23:02:30" Skipping info and debug messages, pass --info and/or --debug to include. Filtering the log data using "processImagePath ENDSWITH "logger"" Timestamp (process)[PID] 2017-04-06 23:02:33.918967+0900 localhost logger[51425]: アババババばばばばb
logコマンドについてはまー man log
すれば雰囲気はわかると思う。この先は君自身の目で確かめてくれ!
これでsyslogに何も出力されなくて途方にくれなくて済みますね。
pry起動時に「Sorry, you can't use Pry without Readline or a compatible library.」と言われる場合あるいはirbで矢印キーが動かない場合
irbで矢印キーを入力するとエスケープ文字が出力されてしまったり、pryを移動させるとエラーになってしまう場合の対処。
OSのバージョンをSierraにしたからか、irbやpryがうまく動かなくなってしまった。
# bundle exec pry Sorry, you can't use Pry without Readline or a compatible library. Possible solutions: * Rebuild Ruby with Readline support using `--with-readline` * Use the rb-readline gem, which is a pure-Ruby port of Readline * Use the pry-coolline gem, a pure-ruby alternative to Readline bundler: failed to load command: pry (/private/tmp/hoge/vendor/bundle/bin/pry) LoadError: dlopen(/Users/sugamasao/.rbenv/versions/2.3.1/lib/ruby/2.3.0/x86_64-darwin15/readline.bundle, 9): Library not loaded: /usr/local/opt/readline/lib/libreadline.6.dylib Referenced from: /Users/sugamasao/.rbenv/versions/2.3.1/lib/ruby/2.3.0/x86_64-darwin15/readline.bundle Reason: image not found - /Users/sugamasao/.rbenv/versions/2.3.1/lib/ruby/2.3.0/x86_64-darwin15/readline.bundle /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/default.rb:151:in `require' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/default.rb:151:in `lazy_readline' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/default.rb:6:in `block in <class:Default>' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/default.rb:125:in `instance_eval' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/default.rb:125:in `block (2 levels) in <class:Default>' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/behavior.rb:54:in `public_send' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/config/behavior.rb:54:in `method_missing' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/history.rb:19:in `restore_default_behavior' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/history.rb:14:in `initialize' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/pry_class.rb:33:in `new' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/pry_class.rb:33:in `history' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/pry_class.rb:222:in `load_history' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/pry_class.rb:129:in `initial_session_setup' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/cli.rb:206:in `block in <top (required)>' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/cli.rb:83:in `block in parse_options' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/cli.rb:83:in `each' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/lib/pry/cli.rb:83:in `parse_options' /private/tmp/hoge/vendor/bundle/gems/pry-0.10.4/bin/pry:16:in `<top (required)>' /private/tmp/hoge/vendor/bundle/bin/pry:23:in `load' /private/tmp/hoge/vendor/bundle/bin/pry:23:in `<top (required)>'
調べてみると、どうも readline
がおかしいらしい。
readlineを入れ直す
複数バージョン入っていたので一度全て消してインストール
$ brew uninstall readline Uninstalling /usr/local/Cellar/readline/7.0... (45 files, 2M) readline 6.3.5, 6.3.8 are still installed. Remove all versions with `brew uninstall --force readline`. $ brew uninstall --force readline Uninstalling readline... (92 files, 4M) $ brew install readline ==> Auto-updated Homebrew! Updated 2 taps (homebrew/core, homebrew/science).
Rubyを入れ直す
rbenvなのでrbenvでuninstallしてinstallする
$ rbenv uninstall 2.3.1 rbenv: remove /Users/sugamasao/.rbenv/versions/2.3.1? y $ rbenv install 2.3.1
これでpryを起動したりするとうまく動くようになった。やったー