倒れるときは前のめり。

カレーが好きです。

ストレングスファインダーで自分の資質をあらためて見直してみた

いろいろあってここ最近は任天堂の岩田さんのインタビュー記事を読み直すことが多くなった。というのも今年で 30 になってしまったこともあり「そろそろ自分もなるべく省エネで周囲に価値を発揮できる分野に力を入れていく頃合いかな」と思考がシフトしてきたからだ。

ご褒美を見つけるという才能 - hobo nikkan itoi shinbun - 1101.com

記事の中でとくに印象に残ってるのはこのセリフ(太字は cheezenaan による強調)。

好きじゃないけど得意なこともありますし,好きだけど,実はあんまり得意じゃないよっていうことも結構あって。(略) 自分の労力の割に周りの人がすごくありがたがってくれたり,喜んでくれたりすることってあるじゃないですか。要するにね,「それがその人の得意な仕事なんだ」って話で。逆に,自分的にはすごい努力して,達成感もたっぷりあるのに,周りからは「はあ?」みたいに思われることもあって。それはね,本人が好きだったとしても,実は不得意なことかもしれないんですよ。 ― 任天堂・岩田氏をゲストに送る「ゲーマーはもっと経営者を目指すべき!」最終回――経営とは「コトとヒト」の両方について考える「最適化ゲーム」 - 4Gamer.net

ちょうど今長めの夏休みをとっていることもあり、サクッとストレングスファインダーを使って自分の資質 ≒ 強みを測定することにした。

ストレングスファインダー

自分の資質(強み)上位 5 つはこちら。

  1. 共感性

    共感性という資質を持つ人は、自分を他人の状況に置き換えて考えることにより、他人の感情を察することができます。

  2. 原点思考

    原点思考という資質を持つ人は、過去や原型について考えるのが好きです。過去を調べることにより、現在を理解します。

  3. 戦略性

    戦略性という資質を持つ人は、目的に向かうための選択肢を想定することができます。いかなる想定に直面しようとも、適切なパターンと問題点を直ちに予測することができます。

  4. 学習欲

    学習欲という資質を持つ人は、学習意欲が旺盛で、常に向上を望んでいます。特に結果よりも学習すること自体に意義を見出します。

  5. 最上志向

    最上志向という資質を持つ人は、強みを利用して、平均的ではなく最高の水準を、個人ないしは集団において追求します。単なる強みを最高レベルのものに変えようとします。

それぞれの資質の特徴を読んだ時点では「まぁなるほどなぁー」という程度の感想だったんだけど「強みのインサイトレポート」という個々人のテスト結果に応じて資質をより具体的に説明してくれるレポートがなかなかよかった。「いったいどこから自分の生活を観察していたんだ」と言いたくなるほどリアリティの高い記述で、テスト結果への納得度がより高まった。

せっかくなので「強みのインサイトレポート」の内容をざっと紹介してみる。なお自分の中でより印象に残ったフレーズは太字にしている。

共感性

おそらくあなたは、難問や困難を解決する能力を生まれつき持っているでしょう。自分自身の作業に集中できると、実行可能な解決策が浮かぶでしょう。しかし、グループで作業する必要があるときは、自分の目標が達成しづらいと感じることがあるかもしれません。あなたは本能的に、自分がある特定の人の気分、動機、考え、または行動をしっかりと認識していると自信を持っているかもしれません。多くの場合、あなたは、周りの人から、プライベートな心配事や感情を相談されるような人でしょう。あなたには、人の経験を理解する才能があるのかもしれません。その洞察力は、時に、適切な質問をしたり、サポートを与えたりするのに、役立ちます。生まれながらにして、あなたは、ときどき、ある人の才能、スキル、知識が、他の人に欠けている面をどう補うことができるか気づくことがあります。グループとして問題を解決する能力は、メンバーの多様性にかかっていると気付いているのかもしれません。あなたは個人の経歴、才能、経験、態度、年齢、教育レベル、文化を知りたいのかもしれません。そのため、あなたは自分がチームを編成して困難な課題に対処する用意ができていると感じているかもしれません。持っている才能によって、あなたは、たまに、一位になりたい、チャンピオンになりたいと思うことがあります。あなたは対戦相手の気分を読めるのかもしれません。勝ち、負け、引き分けへの態度から相手のことがわかるのでしょう。

まぁせやなって感想。人と会話を重ねるごとにいろんな情報が脳内にマッピングされていくというか「困ったらこの人に聞けばいい」リストが勝手にできあがっていくイメージ。

原点思考

持っている才能によって、あなたは、歴史は繰り返すと信じているかもしれません。現在の出来事は過去の出来事の単なる反映であると考えることもあるかもしれません。あなたの心の中では、すでに発生した出来事によって、現在というものが説明され、また将来も予測できるかもしれません。生まれながらにして、あなたは、初めて会った人にたくさんの質問をするかもしれません。相手の過去について好奇心や興味を抱くため、相手をより良く理解して関係を深めることができる場合があります。強みによって、あなたは、ときどき、過去に熱心に学ぶことがあります。なぜそうするかと言うと、今後数か月、数年、数十年に関するヒントを与えてくれるからかもしれません。過去に起こったことについて納得できれば、これから起こる変化や機会によりうまく対処できると感じているのでしょう。 多くの場合、あなたは、過去の出来事を分析することで、人生がより豊かになるかもしれません。過去の経験を思い起こすと、今やっていることや、これまでに達成したこと、出会った人々に対する気分が高まるのでしょう。おそらくあなたは、今日の人々や出来事に与えた影響を理解するために、歴史的事件を調査することがあります。過去に起こった出来事を知ることは、現在の状況や特定の個人の行動を理解するのに役立つのでしょう。

歴史小説や伝記を読むのが好きだったからなぁ。学生の頃に『坂の上の雲』や『竜馬がゆく』を一気読みしたのが懐かしい。あとはふだんの業務を行う際にインスタントなブログ記事だけじゃなくて原理原則が書かれた書籍なり公式のドキュメントなり GitHub の README や issue にあたったり、プロダクトのソースコードを延々と git blame したり関連するチケットやドキュメントを追いかけたりしてる。これももしかしたら「原点思考」か?

戦略性

持っている才能によって、あなたは、自分が、出来事、データ、または人の行動における特定の構成を発見する能力を備えていると気づいているでしょう。あなたはおそらく、傾向や潜在的な問題を他の人が気付く前に識別するでしょう。 あなたは措置を講じた場合、また装置を講じなかった場合の結果を査定するのを手伝うことがあります。強みによって、あなたは、他の人たちが問題に気付く前に、解決方法を見つけることがあります。チームメンバー、同僚、クラスメートなどが質問を理解する前に、その答えを練り始めることがあります。 ときには、事前に数々のアイデアを生み出しておき、その中から特定の状況で最も意味のあるアイデアを選択することがあります。あなたは本能的に、あなたにはなかなか解消されない問題への解決策がいくつもぱっと思い浮かぶことがあるようです。ときどき、それぞれの選択肢を数多くの角度から検討することがあります。状況全体を慎重に評価して、最も妥当そうな選択肢を選ぶのかもしれません。なぜそうするかと言うと、ライバルを得点やパフォーマンスで出し抜きたいのかもしれません。おそらくあなたは、考えたり仕事したりするために一人になる時間が必要な、自立心の強い人のようです。 定期的に、革新的なアイデアを生み出したり、体系的な行動計画を提案したりしています。あなたは、人々の行動やプロセスの機能性、問題が発生する可能性などにおいて繰り返し現れる特定のパターンが見つけられるのかもしれません。多くの場合、あなたは、自分の革新的な考えを生み出す才能を信じるときもあります。1 つの目標に到達するための複数の方法を考え付くことがあります。あなたの次のステップは、いくつかの選択肢の中から最も優れた 1 つの方法に絞り込むことでしょう。あなたは、現在の状況、利用可能なリソース、予算上の制約、差し迫る期日などを考慮することもあるでしょう。

納得感高い。チケットのプランニングで改修箇所の目星をつける際に、とくにドメイン知識があるわけではないけれど、自分が先回りして見つけることがたまによくあった。あとはチケットの実装方針を改修コストやリリース速度をふまえて複数のやり方を提示して PO とすり合わせるみたいなこともわりとよくやってたなぁ。

学習欲

強みによって、あなたは、特定のことについて精通したいと思うこともあるでしょう。あなたの持っている他の才能にもよりますが、1 つの話題を深く理解したいと思ったり、多くの課題を基本的なレベルで把握したいと思ったりするかもしれません。どのようなスタイルであれ、あなたはある特定の人たちのコメントに関心を寄せるかもしれません。人が興味深い情報を共有してくれた場合、あなたはその人に対して、「あなたの洞察は素晴らしいですね。もっとお考えをお聞かせくださると嬉しいのですが」という気持ちを言葉や態度で伝えることがあるでしょう。おそらくあなたは、上級コースや成績優秀者クラスに登録しているかもしれません。それは、理解することが簡単ではないテーマに惹きつけられるからです。自分を充分に信頼して、精神的な忍耐強さや機敏さを試すことがあるでしょう。多くの場合、あなたは、やり遂げたい課題に、すべての力を注ぐことがあります。あなたは、しなければならないことや特定の課題にどのように対処すべきかを調べることがあります。好奇心が、あなたを面白い人や資料、インターネット、授業、雑談、個人的な経験などの情報源に導くと言えます。あなたは、今日、昨日より多くのことを知っていれば、満足できるのかもしれません。あなたは本能的に、たまに、どのような要因で人が特定の行動を取ったのかを究明することがあります。ときには、特定の出来事が起った原因の根拠となる証拠を提供することがあります。一部の人は、合理的な理由を得るために、あなたを頼りにするでしょう。持っている才能によって、あなたは、ある人々の行動を観察したり、彼らの言葉に耳を傾けたりすることで、彼らと親しくなります。 あなたは質問し、彼らの答えを検討することがあります。その結果、その人にとって特別な意味を持つような方法で、その人に対して反応することができるようです。あなたは人の才能、好み、お気に入りの話題などを知っていると、彼らの興味、嗜好、スタイルなどに合わせて言葉や行動を変えることができるかもしれません。

個人的にもっとも同意できた資質がこれ。関心のある分野がコロコロ変わって深く突き抜けた分野ができていかないのが自分の課題ポイント。「特定の出来事が起った原因の根拠となる証拠を提供する」という記述が「学習欲」に登場するのが興味深い。

最上思考

おそらくあなたは、他の人が自分の成功に満足感を得られるようにするのを楽しむかもしれません。あなたはおそらく、ある人が自分の成果を軽くみたり無視したりしないようにするでしょう。持っている才能によって、あなたは、ときどき、自分が複雑な問題、ジレンマ、または難題を解明できると信じることがあります。あなたはおそらく適切な解決策や正しい回答を直感的に見つけ出すでしょう。 多くの場合、あなたは、自分が自然にしていることや得意なことに注意を払うようにしています。時折、特定の分野の知識を深めたり、特定の技術を磨いたりすることを試みることがあります。あなたはおそらく、特定の才能を使うことで優秀になろうという意欲があるのでしょう。あなたは、自分の弱みを克服するために時間やエネルギー、費用を無駄遣いしたくないのでしょう。あなたは、自分が得意なことに集中することもあります。それこそが、やりがいのある生き方だと思っているのかもしれません。あなたは本能的に、人の個性や特性を見つけ出すかもしれません。生まれながらにして、あなたは、特定の人たちに比べて、やや辛抱強い(決意が強い)ようです。このことは、あなたが特定の種類の仕事を開始したり、終了したりするときに、あなた自身だけでなく、他の人にもはっきりと分かるかもしれません。

ここ数ヶ月は新メンバーの受け入れを何度か経験したこともあり、会話をしながらどんなことが得意そう/苦手そうかみたいなことを探っていたので、それなりに「せやな」感が高かった。先に出てきた「共感性」や「学習欲」に通ずる記述が現れるのもポイント高い。

参考: MBTI

じつは今回のストレングスファインダーをやる前にも性格診断テストみたいなのには手を出していて、たとえば 16 類型で性格をタイプ分けした MBTI(Myers-Briggs Type Indicator) によると自分は「仲介者(INFP-T)型」に分類されるらしい。

“仲介者”型の性格 (INFP-A / INFP-T) | 16Personalities

仲介者型気質の人は、真の理想主義者で、極悪人や最悪の出来事の中にさえも、常にわずかな善を見い出し、物事をより良くするための方法を模索しています。落ち着きがあり控えめで、内気にさえも見られますが、内には激情と情熱があり、まさに光を放つ可能性を秘めています。

とくに印象に残っている記述はこちら(太字は cheezenaan による強調)。

他の外向型とは異なり、仲介者型は、ごくわずかな人々やひとつの価値ある目的にのみに集中し、一度に多くのことをやろうとすると力尽き、さらには世の中のあらゆる修復不可能な悪に落胆して、打ちのめされることさえあります。 善を探求するあまりに自分自身を見失い、生きて行く上で欠かせない日常生活の維持を疎かにしてしまう可能性もあるので注意しましょう。仲介者型の人達は、他の性格タイプよりも、よく思いにふり、楽しみながら物事をあれこれ想定したり、哲学的な事柄について思い巡らせたりします。放っておくと、まるで隠者のように引きこもったまま連絡が途絶え、友人やパートナーが、多大なエネルギーを費やして、現実世界に連れ戻すことになります。

マルチタスク苦手なのもそのとおりだし物思いに耽るのも好きだし、気を抜くと周囲の連絡を総スルーして延々と引きこもってしまうしでどうにかしないとなぁ(できるのか!?)という感想。

雑感

あらためて自分の性格なり資質を第三者の目線で言語化してもらうと「なるほどなぁー」と感心することが多かった。今回の記事では紹介しなかったけどストレングスファインダーにはそれぞれの資質を活かすためのアドバイスも記載されているので、定期的に読み直してよしなに実践していきたい。もし余裕があればチームビルディングの一環として、所属している組織なりチームでストレングスファインダーの結果を見せあうといった取り組みもアリかもしれない。

ちなみにタイトルに「あらためて」とあるのは、数年前(たしか学生の頃)に一度ストレングスファインダーをやったことがあったから。なおテスト結果はもう覚えていない。

参考 URL

シェルを zsh から fish に乗り換えたらモノクロームだった日常がカラフルに色づきはじめた

Tl;dr

控えめに言って最高でした。

やったこと

コミットを追っていってください :pray:

Introduce fish

平成生まれの非 POSIX シェル。 Friendly Interactive SHell の略称らしい。

bashzsh とは異なり、オートコンプリートなどの便利機能が設定不要でいきなり使えることが大きな特徴。

brew install fish

chsh -s でログインシェルにはせずにターミナル側でよしなに fish を呼び出してやる。 iTerm2 の場合は Preferences > General > Command から /usr/local/bin/fish を指定してやれば OK。

設定ファイル

$HOME/.config/fish/config.fish に記述する。ターミナル上から fish_config と入力すると Web ブラウザ上から fish の設定を変更できる。

f:id:cheezenaan:20180625185745p:plain

fisherman でプラグイン管理

curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman

zsh でいうところの zplug 的なやつ。使い勝手的には gem とか bundler っぽい。

fzf と ghq を fish でも使えるようにする

zplug 経由で ghq を導入できたが fisherman には対応するものがないので素直に homebrew からインスコする。

brew install ghq fzf

fish 上から fzf や ghq を操作するプラグインがあるのでよしなにインスコ

fisher decors/fish-ghq fzf

自動補完

fish_update_completions

man コマンドから補完を自動生成してくれるらしい。なにこれやばい。

環境変数の定義

bashzshexport PATH=/usr/local/bin:$PATH としていたのを set -x PATH /usr/local/bin $PATH と変更していく。

環境変数の定義をしていくと、セッションを呼び出すたびに PATH がどんどん長くなる問題にぶち当たった。 set -x の使い方に問題があったので、 fish.config の末尾にこんなワンライナーを付け足して解消した。

# ./config/fish/config.fish

# Remove redundant paths
set -x PATH (echo $PATH | tr ' ' '\n' | sort -u)

スペース区切りで並んだ $PATH から sort -u で重複を削除している。

エイリアスの設定とか

zsh で使用していたエイリアス集を別ファイルから読み込ませた。alias foo='bar'alias foo 'bar' となっただけで瞬殺で移行できた。

tmux とのつなぎこみ

reattach-to-user-namespace で使用するシェルを fish に変更する。

# ~/.tmux.conf

# ...

set-option -g default-command "reattach-to-user-namespace -l $(which fish)"

ベンチマークしてみた

$ for i in (seq 1 5) ; time fish -ic exit ; end
        0.12 real         0.08 user         0.04 sys
        0.11 real         0.08 user         0.03 sys
        0.11 real         0.07 user         0.04 sys
        0.11 real         0.07 user         0.03 sys
        0.11 real         0.08 user         0.04 sys

な ん で す か 、 こ れ 。

今までの努力はなんだったのか。

所感

手持ちの設定ファイルの量にもよるけど、シュッとデフォルト設定のまま試してみてよさそうなら移行を考えてもいいのでは。自分の場合はそこまでがっつりカスタマイズして zsh 固有のなにかを使ってたわけでもないし、とりあえず ghqfzf が気持ちよく使えればよかったので、今回を機に fish へ移行してみて概ね満足している。

pros

  • zsh に比べて設定ファイルの記述量が圧倒的に少なくて済む
    • ゼロコンフィグの波をシェルにも感じる
  • しかも速い!!!!!
    • スピード is 大正義
  • 日本語のドキュメントが充実してるので割と安心

cons

参考資料

fish 全般

rbenv まわり

プロンプトのカスタマイズ

環境変数とか

zsh の設定ファイルを整理して GitHub 上で管理することにした

f:id:cheezenaan:20180624111652p:plain

n 番煎じ感しかないけれど、半年に 1 回は訪れる「開発環境を根本から見直したい欲求」に従うままやってみた。

はじめに

  • .zshrc が育ってきたせいか zsh の起動が遅くなってきた
    • zsh の設定ファイル見直してダイエットしたい
  • これまでは Mackup で Dropbox 上に設定ファイルをバックアップしていた

Tl;dr

$ git clone git@github.com:cheezenaan/dotfiles.git ~/dotfiles
$ cd ~/dotfiles
$ sh /setup.sh
# That's all!

やったこと

ディレクトリ構造を見直した

$ tree ~/dotfiles -a -I .git
.
├── .zsh
│   ├── .zshenv ... 環境変数(PATH や EXPORT) を定義
│   ├── .zshrc ... rc/ 以下の設定ファイルを読み込ませたり autoload を定義してる
│   └── rc
│       ├── aliases.zsh ... もろもろのエイリアス集
│       ├── keybindings.zsh ... カスタムキーバインド集
│       ├── options.zsh ... setopt をまとめて定義
│       ├── plugins.zsh ... zplug で使用するプラグイン集
│       └── variables.zsh ... もろもろの変数集
├── .zshenv ... ただのエントリーポイント
├── README.md
└── setup.sh ... ホームディレクトリにシンボリックリンクを貼るシェルスクリプト

/dotfiles 直下の .zshenv$ZDOTDIR を定義して source $ZDOTDIR/.zshenv をするだけで、設定の実態は /.zsh/ 以下のファイルで行うようにした。

zplug でプラグイン管理する

prezto は使い勝手こそよかったのだけど基本全部入りなため、シェルの起動に時間がかかりがちだった。必要なものだけをプラグインとして読み込ませるようにすれば多少はマシになるのでは…という思いからプラグインマネージャーの導入を検討。 prezto などの外部ライブラリのプラグインやテーマも管理できる点に惹かれて zplug を採用。 README が充実してるのも好印象。

自分が入れているプラグインの一覧は以下の通りで、 prezto からは autocompletion 用の module を持ち込んだ。あれがないと生活できない身体になってしまったのでな…。

# .zsh/rc/plugins.zsh

# Clone zplug if not exist
if [[ ! -d ~/.zplug ]]; then
  git clone https://github.com/zplug/zplug ~/.zplug
fi

source ~/.zplug/init.zsh

# zsh plugins
zplug "zsh-users/zsh-autosuggestions"
zplug "zsh-users/zsh-completions"
zplug "zsh-users/zsh-syntax-highlighting", defer:2

zplug "junegunn/fzf-bin", as:command, from:gh-r, rename-to:fzf
zplug "mafredri/zsh-async", from:github
zplug "mollifier/anyframe", lazy:true
zplug "motemen/ghq", from:gh-r, as:command, rename-to:ghq, lazy:true
zplug "sindresorhus/pure", use:pure.zsh, from:github, as:theme

zplug 'modules/utility', from:prezto
zplug "modules/completion", from:prezto

# Install uninstalled plugins
zplug check --verbose || zplug install
zplug load

peco から fzf に乗り換えた

これまで peco を使っていて不満もなかったけど、見た目がより好みだったのでこの機に乗り換えてみた。 fzf もまた README が非常に充実しているのがよい。 vim 用のプラグインもあるみたいだけど今回は導入見送り。

もともと anyframe を使用していたおかげで peco からの移行もスムーズ。

シンボリックリンクを貼るシェルスクリプトを用意した

dotfiles.git のシンボリックリンク$HOME 以下に貼り付けるかんたんなスクリプトをシュッ書いた。

#!/bin/sh

basepath=$(
   cd $(dirname $0)
   pwd
)

if [ ! -d ~/.zsh/rc ]; then
    mkdir -p ~/.zsh/rc
fi

ln -sf $basepath/.zshenv ~/.zshenv

for rcfile in .zsh/rc/*; do ln -sfv $basepath/$rcfile ~/.zsh/rc; done
for zfile in .zsh/.z*; do ln -sfv $basepath/$zfile ~/.zsh; done

ベンチマークをとった

$ for i in $(seq 1 5) ; do time ($SHELL -l -ic exit) ; done
( $SHELL -l -ic exit; )  0.43s user 0.46s system 102% cpu 0.867 total
( $SHELL -l -ic exit; )  0.41s user 0.44s system 103% cpu 0.822 total
( $SHELL -l -ic exit; )  0.44s user 0.48s system 100% cpu 0.919 total
( $SHELL -l -ic exit; )  0.44s user 0.48s system 96% cpu 0.954 total
( $SHELL -l -ic exit; )  0.43s user 0.47s system 102% cpu 0.877 total

整理前は 2 ~ 3 秒かかっていたことを考えると、1 秒未満ならまぁ許容範囲…だと思いたい。

まとめ

homebrwe で zsh さえインストールしさえすれば、 git cloneスクリプトを実行するだけで、シェル周りの環境が整うようになってとても気持ちがいい。今までなんとなくで書いていた .zshrc まわりの設定ファイルの意味や読み込み順が理解できたし、役割ごとにファイルを分割したことで少しはメンテナンスしやすくなったと思う。頃合いを見て vim やほかの CLI ツールの設定ファイルもも dotfiles リポジトリに移していきたい。

参考資料

zsh 全般

zplug

fzf / peco + anyframe

Docker for Mac と Dinghy のパフォーマンスを比較してみた

はじめに

Mac x Docker 環境下で Rails アプリを開発している際にどれくらい性能差が出ているのか、n 番煎じであることは承知の上で実際に試してみた。

検証環境(ホスト)

検証環境(Docker)

Docker for Mac も Dinghy も共通して、 VM には CPU 2 コア、メモリーを 8GB 割り当てる。

For Mac

$ docker -v
Docker version 18.03.1-ce, build 9ee9f40

$ docker-compose -v
docker-compose version 1.21.1, build 5a3f1a3

stable 版だとディスクイメージのフォーマットに qcow2 を使用しているけど、今回の検証では raw に変更する。

vim ~/Library/Group\ Containers/group.com.docker/settings.json

diskpPath の拡張子 qcow2raw に変更したら Docker.app を再起動する。 手っ取り早く変えるには↓のワンライナーを叩く。

sed -i -e 's/qcow2/raw/g' ~/Library/Group\ Containers/group.com.docker/settings.json

PreferencesDisk > Disk image location に記載されたパスの拡張子が raw になっていれば OK。

Dinghy

$ docker -v
Docker version 18.05.0-ce, build f150324

$ docker-compose -v
docker-compose version 1.21.2, build unknown

$ docker-machine -v
docker-machine version 0.14.0, build 89b8332

$ docker-machine inspect dinghy
{
    "ConfigVersion": 3,
    "Driver": {
        "IPAddress": "192.168.99.100",
        "MachineName": "dinghy",
        "SSHUser": "docker",
        # ...
        "CPU": 2,
        "Memory": 8192,
        "DiskSize": 20000,
        # ...
    },
  # ...
}

検証方法

Rails チュートリアルで作成していたサンプルアプリの RSpec を回す。

$ bundle exec rake stats --all
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |    291 |    218 |      10 |      34 |   3 |     4 |
| Helpers              |     81 |     63 |       0 |      12 |   0 |     3 |
| Jobs                 |      4 |      2 |       1 |       0 |   0 |     0 |
| Models               |    135 |     94 |       4 |      14 |   3 |     4 |
| Mailers              |     21 |     14 |       2 |       2 |   1 |     5 |
| Channels             |     12 |      8 |       2 |       0 |   0 |     0 |
| Libraries            |      0 |      0 |       0 |       0 |   0 |     0 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total                |    544 |    399 |      19 |      62 |   3 |     4 |
+----------------------+--------+--------+---------+---------+-----+-------+
  Code LOC: 399     Test LOC: 0     Code to Test Ratio: 1:0.0
$ docker-compose run --rm --service-port spring sh

して Docker コンテナに入ってから

$ bundle exec rails db:create db:migrate
$ for i in $(seq 1 10); do time bundle exec rspec --profile --format progress; done;

を実行した。とりあえず 10 回くらい回せばええやろ。

結果

数値の単位はいずれも秒(sec) です 。

for Mac

Dinghy time - real RSpec - Finished in RSpec - files took to load
Ave 39.86 34.44 4.58
Min 35.34 31.31 2.99
Max 51.09 40.98 12.98

Dinghy

Dinghy time - real RSpec - Finished in RSpec - files took to load
Ave 39.84 34.99 3.96
Min 35.55 29.73 3.47
Max 45.55 40.93 4.62

考察とまとめ

rspec コマンドの呼び出しから終了までにかかった実時間(time - real の項目)も RSpec の実行時間(RSpec - Finished in の項目)も、 Docker for Mac と Dinghy とで目に見えた差が生じなかった。

今回使用した Rails チュートリアルくらいの規模のアプリケーションであれば、 Docker for Macraw フォーマットを使用してボリュームマウントで cached オプションを指定してやれば、 Dinghy と同じくらいのパフォーマンスを発揮してくれる…と言ってよさそうなのかな。

実際にプロダクションで 5 年とかのスパンで運用しているようなそれなりに大きい規模の Web アプリケーションでどれくらいパフォーマンスに差が生じるかは今後の課題ということで、どなたかお願いします(他力本願

参考資料

TypeScript + Webpack4 な素振り環境を作った

今さらながら TypeScript で静的型付けに入門したくなったので、サクッと素振り環境を作ってみた。

tl;dr

docker-compose run --rm yarn install
docker-compose up

ゴール

  • ローカル PC に依存せずに TypeScript を書いてコンパイルできる環境を作る
    • node のバージョン違いで yarn install 落ちたりつらい
    • yarn コマンドも Docker コンテナ上で叩く(Mac 上で Docker 動かすと I/O 遅くてつらいけど)

Webpack 4

docker-compose run --rm node yarn add -D webpack webpack-cli webpack-serve

webpack-dev-server の後継らしい webpack-serve を導入してみた。

TypeScript さえビルドできればいいので余計な Loader とかプラグインを入れてないからかもしれないけど webpack.config.js がわりとスッキリしていてよい。

Introduce TypeScript

docker-compose run --rm node yarn add -D typescript ts-loader
docker-compose run --rm yarn tsc --init

生成された tsconfig.jsonStrict Type-Checking OptionsAdditional Checks をすべて有効にしておく。

Introduce Linter / Formatter

TSLint を使うか ESLint に TypeScript のパーサーを突っ込んで使うか選択肢があるらしいんだけど、 ESLint のほうが設定できるルールが多いらしいので後者を採用(要調査)。

Vue.js 向けの ESLint プラグインを公式が用意しているのも、なにげに評価高い。

ESLint

docker run --rm node add -D eslint eslint-conifig-airbnb-base eslint-plugin-import typescript-eslint-parser eslint-plugin-typescript

React(JSX) 抜きで普遍的に使える構成にしたかったので eslint-config-airbnb ではなく eslint-config-airbnb-base を導入した。 eslint-plugin-typescript はおまけ。

Prettier

docker run --rm node add -D prettier eslint-config-prettier eslint-plugin-prettier

問答無用で入れる。 ESLint と併存させるとより幸せになれる。

  • eslint-config-prettier は ESLint 上で Prettier と競合するフォーマット関連のルールを無効にしてくれる
  • eslint-plugin-prettier は Prettier のルールを ESLint が読み込んで、 ESLint 上で Prettier を実行してくれる

.eslintrc

// .eslintrc
{
  "env": {
    "browser": true
  },
  "extends": ["airbnb-base", "plugin:prettier/recommended"],
  "parser": "typescript-eslint-parser",
  "plugins": ["typescript", "prettier"],
  "rules": {
    "no-undef": "off",
    "no-unused-vars": "off",
    "import/extensions": "off",
    "import/no-unresolved": "off",
    "import/prefer-default-export": "off",
    "prettier/prettier": "error"
  }
}

prettier 以外に rules に追加しているのは以下:

  • "no-undef": typescript-eslint-parser で未対応なので無効化
  • "import/extensions", "import/no-unresolved": import するときに .ts および .tsx を解釈してくれないので無効化
  • "import/prefer-default-export": 1 ファイルで 1 つだけ export const するときに不便なので消した

参考

Tachikoma.io でライブラリ依存関係を自動チェックさせてみた

はじめに

  • 素振り用の Rails 開発環境で、 Gemfile の脆弱性アラートが出現していた
  • とはいえ手動で bundle update する仕事つらい
  • tachikoma.io を使うと自動で依存関係をチェックして差分があれば PR を作成してくれるらしいので入れてみる(イマココ

Tachikoma.io を入れてみる

Tachikoma.io がライブラリ依存地獄を取り除いてくれます。あなたがやりたいのは依存のアップデートですか?アプリケーションを書くことですか?

Tachikoma.io のできることは Tachikoma.io に任せて、あなたはあなたのやりたいことをやろう。

なにこれ素敵…!ということで即導入。GitHub 連携して、適用したいリポジトリにチェックを入れるだけ。3分クッキングよりもかんたん。

設定ファイルを追加する

Configuration - Tachikoma.io

Rails アプリケーションに Tachikoma.io を使用したい場合は、明示的にストラテジーbundler にしてやる必要がある。

ルートディレクトリに .tachikoma.yml を置いて、

# .tachikoma.yml
strategy: 'bundler'

あるいはターミナル上から ↓ の command を叩く。

# Download setting about strategy for bundler
$ curl -O http://tachikoma.io/example/bundler/.tachikoma.yml

使用例

こんなぐあいに PR を作成してくれる。CI が通っていれば即 master にマージ。所要時間 n 分。優しい世界。

Rails on Docker な素振り環境の Rails バージョンアップをした(v5.1.4 => v5.2.0)

タイトルの通り。所詮サンプルアプリケーションだし楽勝かな…と思ったが意外なところで躓いたので、備忘録として残しておく。

5.2.0 に上げる

Gemfile の Rails のバージョン指定を ~> 5.2.0 に修正して、

bundle update rails

からの

bin/rails app:update

いろいろとファイルが書き換えられてしまうので、よしなに git diff しながら目視で確認していく。

テストが落ちる

覚悟はしていたのだけど、Rails のバージョン上げたらテストが落ちるようになった。エラーメッセージを読みつつ binding.pry を適宜はさみながらデバッグして直していった。

Helper Spec が落ちる

たとえばこれ

https://github.com/cheezenaan-sandbox/sample_app_rev4/commit/1925113

Failures:

  1) UsersHelper gravatar_for when user is present when email is present
     Failure/Error: end

     ArgumentError:
       Can't resolve image into URL: undefined method `to_model' for #<Pathname:0x0000556238b7cd58>
       Did you mean?  to_yaml
     # ./app/helpers/users_helper.rb:11:in `gravatar_for'
     # ./spec/helpers/users_helper_spec.rb:7:in `block (3 levels) in <top (required)>'
     # ./spec/helpers/users_helper_spec.rb:31:in `block (5 levels) in <top (required)>'
     # -e:1:in `<main>'
     # ------------------
     # --- Caused by: ---
     # NoMethodError:
     #   undefined method `to_model' for #<Pathname:0x0000556238b7cd58>
     #   Did you mean?  to_yaml
     #   ./app/helpers/users_helper.rb:11:in `gravatar_for'

v5.2.0 へ上げた際に落ちるようになった。どうやら image_tag が怪しそうので git diff v5.1.4..v5.2.0 actionview/lib --stat しながら Rails のコードを追っていくと、AssetTagHelper#image_tag に修正入ってた。たぶん ActiveStorage もろもろの対応の影響なんだろう。

# actionview/lib/action_view/helpers/asset_tag_helper.rb
def image_tag(source, options = {})
  options = options.symbolize_keys
  check_for_image_tag_errors(options)
  skip_pipeline = options.delete(:skip_pipeline)

  # このへんが v5.2.0 へ向けて追加された箇所っぽい
  options[:src] = resolve_image_source(source, skip_pipeline)

  if options[:srcset] && !options[:srcset].is_a?(String)
    options[:srcset] = options[:srcset].map do |src_path, size|
      src_path = path_to_image(src_path, skip_pipeline: skip_pipeline)
      "#{src_path} #{size}"
    end.join(", ")
  end

  options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
  tag("img", options)
end

ref. https://github.com/rails/rails/compare/v5.1.4...v5.2.0#diff-d36c3bf0d0a61b0b5dbae953a4852ad2R332

image_tag -> resolve_image_sourceからの、 polymorphic_url(source) へ進んだ先で to_model に反応できなくなって落ちるようになったようす。

# actionview/lib/action_view/helpers/asset_tag_helper.rb
def resolve_image_source(source, skip_pipeline)
  if source.is_a?(Symbol) || source.is_a?(String)
    path_to_image(source, skip_pipeline: skip_pipeline)
  else
    polymorphic_url(source) # <= これ
  end
rescue NoMethodError => e
  raise ArgumentError, "Can't resolve image into URL: #{e}"
end

ref.

なので、明示的に Pathname#to_s してやった。ここまでで System Spec 以外のテストが通るようになった。

bin/rspec spec/helpers spec/models spec/requests

System Spec が倒せない

たとえばこんなかんじ。

~/s/g/c/c/sample_app_rev4 » docker-compose exec spring bin/rspec spec/system/static_pages_spec.rb --fail-fast               bump_rails_v5.2 ✔
Running via Spring preloader in process 103

StaticPages
  Home page
Capybara starting Puma...
* Version 3.11.4 , codename: Love Song
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:40933
    should have title "Ruby on Rails Tutorial Sample App" (FAILED - 1)

Failures:

  1) StaticPages Home page should have title "Ruby on Rails Tutorial Sample App"
     Failure/Error: it { is_expected.to have_title full_title }
       expected "" to include "Ruby on Rails Tutorial Sample App"

     [Screenshot]: tmp/screenshots/failures_r_spec_example_groups_static_pages_home_page_example_at___spec_system_static_pages_spec_rb_13_223.png


     # ./spec/system/static_pages_spec.rb:13:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

Finished in 4.12 seconds (files took 4.18 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/system/static_pages_spec.rb:13 # StaticPages Home page should have title "Ruby on Rails Tutorial Sample App"

Coverage report generated for RSpec to /app/coverage. 17 / 45 LOC (37.78%) covered.

なるほど puma が使われるようになった。

tcp://127.0.0.1:40933…🤔ポート番号がテスト回すたびに変わってるな。このポート番号って Docker で穴を開けてやらんといかんのかな🤔

いろいろと試行錯誤した結果、、Capybara.server_host を明示的に "0.0.0.0" に指定した上で Capybara.server:puma ではなく :webrick にすることで動いた。

# spec/support/capybara.rb
(略)
Capybara.server_host = "0.0.0.0"
# TODO: Use puma as Capybara.server
Capybara.server = :webrick

ref. https://github.com/cheezenaan-sandbox/sample_app_rev4/pull/29/commits/74b13c57

いまいち納得できてないので要調査。

おわりに

Rails バージョンアップ、 いやおうなく Rails 本体のコードを読み進めていくことになるので勉強になるし、これくらいのちっちゃい環境ならいくらでも壊れても問題ないので、積極的にバージョン上げて経験積んでいきたい。

あとは Tachikoma.io で bundle update 自動化していきたい。