Ruby 2.5.0 までの道のり

こんにちは、id:eitoball です。年末・年始は、特別なことをすることなく、自宅で家族とまったりと過ごしていました。正月らしいことは、歩いて5分ぐらいの近所の神社へ初詣に行ったことでした。

昨年2017年12月25日に Ruby 2.5.0 が リリース されました。コミッタの皆様ありがとうございます。Misocaは、翌日26日に2.5.0を使うように更新をしました。今回は、2.5.0 への更新について何かを書こうとしていたのですが、特に苦労することなく更新することができてしまったので、Misoca で Ruby のバージョンの変遷を調べてみました。

f:id:eitoball:20180112100730p:plain

Ruby 1.9.3の時代(2013年から2014年頃)

サービス開始当初、2013年頃は、Ruby 1.9.3-p194 を使っていたようです。1.9.3-p194 は、2012年04月20日に リリース されていました。Misoca の開発が始まった頃の最新のバージョンで、しばらく、このバージョンを使い続けていたようです。

次は、2014年01月頃に Ruby 1.9.3-p484 へ更新しました。2013年12月25日には、バージョン 2.1.0 が リリース されていました。しかしながら、とりあえず、1.9.3 系の最新バージョンへ更新を選択しました。

Ruby 2.x へ(2014年から2016年まで)

Misoca が、Ruby 2.x を使うようになったのは、2014年04月24日に Ruby 2.1.1 へ更新したときでした。2.1.1 の リリース は、2014年02月24日で、この頃に 2.0 系や1.9.3 系もリリースされていましたが、最新の Ruby を使うことになりました。

2014年12月05日には、2.1.5 を使用するようになりました。2015年03月10日に 2.2.0 を使うようになりました。この頃には、2.2.1 が リリース されてたので、2.2.1 を使おうとテストをしていたら、 GC 周りに問題があることがわかり、2.2.0 を使うようにするか、 2.2.2 がリリースするまで待つか迷いましたが、2.2.0 を使うことにしました。

Ruby 2.2.3 を使うようになったのは、2015年08月20日でした。これ以降、以下のように最新のRubyを使うように追従していきました。

  • 2015年12月17日 2.2.4
  • 2015年12月26日 2.3.0
  • 2016年05月06日 2.3.1
  • 2016年11月21日 2.3.2
  • 2016年11月28日 2.3.3

Ruby 2.4 (2017年)

前述のように Ruby 2.2 後半から 2.3 を使うように順調に更新していましたが、2.4.0 を使うようになったのは、2017年03月03日でした。遅くなった理由は、Misoca 社では、前年から rrrspec を使用してテストを実行するようになりましたRuby 2.4.0 を使うように変更してから、ローカルで rspec を使って成功する spec が、時々、失敗するようになり結果が不安定でした。この原因の調査などに手間取ったためでした。

以降は、以下のように新しい Ruby を使うように更新していきました。

  • 2017年03月27日 2.4.1
  • 2017年10月03日 2.4.2
  • 2017年12月15日 2.4.3

Ruby 2.5(2018年)

最初に書いたように昨年末の2017年12年26日にリリースされた翌日に 2.5.0 を使うように更新しました。2.5.0 への更新のために2017年10月頃から、その頃リリースされた2.5.0-preview1 を使ってテストをして準備をしていました。

現在のところ、安定して稼働しており、この記事 で説明されているような改善による効果も確認されているようです。

さいごに

今回、初めて、Misoca が使用する Ruby の更新を振り返ってみました。振り返るにあたり、git のコミットログや GitHub のプルリクエストから、Misoca 社の変化を垣間見ることができ、楽しい経験でした。

Misoca 社では、Ruby の更新などにも興味があるエンジニアを募集しています。

CI実行時間を11分→5分に短縮する

メリークリスマス!🎄

Misoca開発の@kokuyouです。

Misoca Advent Calendar 2017、遂に最終日です。 昨日の記事は@eitoball開発の小ネタ劇場でした。

本日 Ruby 2.5 が出る予定ですが、特に関係ないCIの話をしていきたいと思います。

どうでもいいんですが、CIという略語を見ると Continuous IntegrationなのかCANDY ISLANDなのか迷う今日このごろです。

⏳ ビルド時間の推移

以前の記事で紹介したとおり、MisocaではCIでのRSpec分散実行にrrrspecを使用しています。

これにより20分ほどかかっていたビルドを11分程度まで短縮することができたのですが、それでも11分は結構待たされるな―、という気持ちになります。スピーチとCIのビルド時間は短いほうが良いのです。

そんなわけで、頑張って短縮してみました。

以下は7月~9月ごろのビルド実行時間推移を表したグラフです。

f:id:kokuyouwind:20171225142005p:plain

青線がビルドごとの実行時間、赤線が直前10ビルドの移動平均になっています。

y軸の上限を1000秒(=16分40秒)に取っていますが、初期はこの上限を軽々と突き抜けていることがわかります。 全体的にも600秒(=10分)はまず下回らない感じです。

一方で、対処を始めた8月ごろからグラフが右肩下がりになり、終盤では400秒を下回っています。

直近(10月~12月)では以下の通り、ほとんどのビルドで400秒(6分40秒)を下回り、軽いビルドでは300秒(=5分)程度で完了しています。 なお、たまに飛び跳ねてるのもDependabotで一気にビルドキューが積まれたときのものでした。

f:id:kokuyouwind:20171225142135p:plain

ここまで実行時間が短縮されたことで、待たされていると感じることがだいぶ少なくなりました。

💪 やったこと

💰 金の弾丸

最初は「rrrspecの並列数増やせばスケールするでしょ」と思いmax_workerを5から10に上げてみたのですが、ほとんど短縮せず悲しい気持ちになりました。

仕方がないので、ここからは時間がかかってる処理をひとつずつ調べて潰していく戦略にシフトしました。

🖥 MySQLのローカル同居

当初は レシピに組み込むのがめんどい MySQLの起動オーバーヘッドやメモリ量などを考慮して、rrrspec workerノードとは別にMySQLノードを立てていました。

しかしMySQLノードを固定で立ち上げているとスケールしないことや、接続数・転送量が逼迫していることから、MySQLをrrrspec workerノード内に同居させることにします。

datadirをtmpfsに向けるのに苦戦したり、AppArmorにMySQLプロセスの起動を阻まれたりしたのですが、なんとか完遂し、なぜかこれだけで1分程度実行時間が短くなりました。

帯域とか転送速度の問題でこれまでの戦略がイケてなかったという話なんですが、まぁ結果オーライです。

(この時点でjob全体10min、うちrrrspecが8min)

🔗 rsyncの設定見直し

さらにrrrspecの実行ログを確認したところ、実行対象をrrrspec master -> rrrspec workerへ同期するrsyncが1min以上かかっていました。

以下の設定を見直し、rsyncにかかる時間を5sec程度まで短縮しました。

  • Jenkinsではjobごとにworkspaceを持ちタイムスタンプが異なるため、 --timesではなく--checksum を使う
  • node_modulestmp/cacheなど不要なディレクトリが同期されていたため、--exclude指定に追加する

(この時点でjob全体9min、うちrrrspecが7min)

🔪 specの分割

MySQLがスケールするようになったためmax_workerを再度上げていったのですが、やはりあまり実行時間は短縮されませんでした。

個別に実行時間を見てみると、なんと単独ファイルで7minかかっているfeature specが……

rrrspecはファイル単位で分散実行するため、そりゃ7minは下回れないなぁ…… という気持ちになり、そのspecを幾つかのファイルに分割しました。

その後もボトルネックになったspecを分割したり不要なテストを消したりと地道に潰していった結果、10workerでのrrrspec実行時間を5minまで短縮することができました。

(この時点でjob全体7min、うちrrrspecが5min)

🏗 package install & build

オーバーヘッドの比率が上がってきたため、そちらで時間がかかっている処理に目を向けていきます。

オーバーヘッドのうちbundle installが20sec、yarn installが30sec、yarn buildが1min程度で、依存パッケージ解決と静的ファイルビルドに殆どの時間を使っていました。

ここで依存パッケージは Gemfile.lockyarn.lockが一致していれば同じものを使いまわせますし、yarn buildJavaScriptのソースなどに変更がなければ同じものを使えます。

そこでCircleCI 2.0のキャッシュ機構を参考に、Jenkinsfileでキャッシュを行う関数を用意しました。

def yarn_install() {
  cache(
    ['node_modules'],
    get_cache_key(['package.json', 'yarn.lock']),
    { bash "yarn install --no-progress --pure-lockfile" }
  )
}

def cache(paths, key, callback) {
  if (!fileExists(cachedir(key))) {
    callback()
    for(def path: paths) {
      // node_modulesのrequireの仕様上、ディレクトリ構造の保持が必要なので path/to/file ような場合に path/to までを作成したい
      sh("dirname ${cachepath(path, key)} | xargs mkdir -p")
      sh("mv ${path} ${cachepath(path, key)}")
    }
  }
  for(def path: paths) {
    sh("rm -rf ${fullpath(path)}; ln -s ${cachepath(path, key)} ${path}")
  }
}

cache関数では依存ファイルのパスを元にキーを生成しており、そのキーを持つキャッシュが存在する場合はsymlinkを貼るだけで処理を終わります。

これにより、Gemfileなどに変更がない場合はこれらの処理を合わせて10secちょっとで終わるようになりました。

なおキャッシュを利用するのはfalse positiveが怖いのですが、古いキャッシュはfalse negativeのほうが起こりやすいはずですし、定期的に削除して再生成させているため大きな問題はないだろうと思っています。

✅ 結果

これらの改善処理によって、全体で5min、オーバーヘッドは10sec程度まで短縮することができました🎉

あとは不要なspecを削ったり統合したり、あるいはfixtureを減らしたりcreateからbuildに変えたり、といった地道な改善を続けて少しずつ実行時間を削ることになります。

こういった地道な改善を進める上でも、ひとまずそれ以外の部分で実行時間を大幅に削れたのは効率が良かったと思います。

🎅 Misoca Advent Calendar 2017

最終日がだいぶギリギリになってしまいましたが、無事Misoca Advent Calendar 2017を完走することができました。

個人的には社長の記事が一番バズってるという事実に微妙な気持ちを抱いていますが、全員でいろいろな記事を書くことができて楽しかったです。

来年も気が向いたらアドベントカレンダーを立てたいなーと思います。

📣 宣伝

Misocaでは2018年のアドベントカレンダー記事を一緒に書く仲間を募集しています!!!

開発の小ネタ劇場

こんにちは、id:eitoball です。

この記事は、Misoca Advent Calendar 2017 の24日目の記事です。

今日は、クリスマス・イブですね。明日は、ruby 2.5.0 のリリースが予定されています。もう少し気の利いたことが書くといいのですが、さらっと始めます。

今回は、様々なMisocaのメンバーにエディタやシェルの使い方などといった主に開発に関する小ネタ(ティップス)を紹介してもらいます。

RubyMine で Neovim を使う

by id:eitoball

先日、RubyMine を使うようになったという記事を書きましたが、まだ、vi 系のエディタを使いたいときがあります。RubyMine の「ターミナル」から起動してもいいのですが、ANSI エスケープを正しく処理できないなど若干の問題があるので、正しく処理する iTerm 2 などのターミナルプログラム上で起動する方が快適に編集ができます。

そこで、RubyMine の "External Tools" neovim-remote を使って、快適に Neovim を使うようにします。設定方法は以下のようになります。

  1. このページ で説明されているように neovim-remote を設定します。
  2. RubyMine の "External Tools" で neovim-remote を起動するようにする。以下は設定例です。

screenshot.png (139.1 kB)

これだけになります。後は、ターミナルを開いて NVIM_LISTEN_ADDRESS=/tmp/nvimsocket nvim のように Neovim を事前に起動しておいて、RubyMine でファイルを開いておいて、メニューから "External Tools" -> "neovim" を指定すれば、 Neovim でファイルを開きます。"Keymap" にてショートカットを割り当てておくと便利です。僕の場合は、Shift-Ctrl-Command-V を割り当てています。

Neovim で変更する場合は、RubyMine で自動的に反映されます。RubyMine で変更する場合は、 Neovim では、:e で再読み込みをして反映します。

test.gif (1.1 MB)

注意するのは、事前に Neovim を開いておく必要ことです。開いておかないと RubyMine で「Vim: 警告: 端末への出力ではありません」のようなメッセージが出ます。この場合は、一旦、プロセスを止めて(Stop Process)、NVIM_LISTEN_ADDRESS で指定したファイルを削除してからやり直すようにして下さい。

Happy Editing with RubyMine and Neovim !!!

マルチカーソルLOVE

by id:mugi_uno

普段VSCode/SublimeText/Atomの全てを使っていますが、全てに共通して使える機能であるマルチカーソルが無いと、もう生きていけない体になっています。 (マルチカーソル = カーソルをたくさん作れる機能と思ってください)

例えば、jsonの値を全て初期化時にインスタンス変数に持ちたいな〜みたいなコードを書こうと思った時、こんなことができます。

cap.gif (159.5 kB)

あっ、やっぱキーの名前全部 item_ から始まるんだったわ!みたいなケースでも、検索・置換を行うことなく、サクッと行えます。

cap2.gif (90.2 kB)

使いこなせると手放せなくなるので、使ったことの無い人はぜひお試しください!

AtomのTeletypeで爆速リモートペアプロ

by renyamizuno_

先月末頃にTeletype for Atom というAtomプラグインがでました。 GitHubが「Teletype for Atom」リリース。開発者向けエディタ「Atom」でも、複数プログラマが同時にコード編集可能 - Publickey 複数人でコードを一緒に編集出来るようになりました。 このため、キーボード配列が違うとか、キーバインドが違うから…とかそういった問題でペアプロが難しいといった問題から解消されます。 最高。 主にテストを書く時に、「こういうテストがいるよねー」ということを言いながら雑にテストコードを書いている時に、 ペアがすでに必要なパラメータ等を準備してくれていて、瞬間でテストコードが仕上がる。という事案が何度も発生して、脳が追いつきませんでした。 とても新鮮で不思議な体験だと思うので、みなさんも味わってください。

完全食COMP

by 洋食

皆様、昼食はどうしていますか?Misoca名古屋オフィスは名駅近くにあるので、ランチには事欠きません。が、逆にドコで何を食べるかを考える必要があります。距離と時間(店の行列・料理が出てくるまでの時間・食べる時間)から最適解を求める必要があります。贅沢な悩みではありますが、ちょっと考えるのが面倒になってきました。そこで、完全食COMPです。プロテインみたいなもので、好きな飲み物で溶かして飲むだけです。味はほぼ豆乳と同じです。私は、カフェインを摂取したいので、コーヒーで溶かしています。朝にCOMPを作って、水筒に入れて持っていっています。ドコで何を食べるかを考える必要もなく、お弁当を用意する必要もない。私の趣味は読書ですが、昼休みがまるまる空くので、本とか論文が読み放題です。流石に夕方にお腹が空いてきますが、Misocaは残業しない主義なので、帰宅して夕食たべればOKです。最高です。

RubyMineでもマルチカーソルが使えるぞ〜

by ころちゃん

こんにちは、RubyMine(IntelliJ)勢です。記事上のほうで、Sublimeおじさんがマルチカーソルを絶賛していますが、RubyMine でもマルチカーソルは使えます。

Shift + Alt + Click または Alt + Alt 押しながら↑↓ です。

実は前者だけ知っていて、クリックするの面倒だな〜って思ってたけど後者があればマウス使う頻度も減りますな。あと同じ単語にマルチカーソル生やすときは、Ctrl + g でいけます。

普段、息を吸う用にShift + Shiftサーチ(Search Everywhere)してましたが、Alt + Altがあるとは思いませんでした。。灯台下暗しでしたね。ちゃんと覚えよう。

最後にさらっとRubyMineを使う際の知見/感想を書いておくと

  • IdeaVim等を入れると、デフォルトのショートカットと競合するので、Vimキーバインドを使うのをやめた。
  • ショートカット数が膨大なので、慣れるまではデフォルトをおすすめする。
  • 画面分割した際のSplitter間の移動ショートカットがデフォルトで設定されてないので、Tab to Next Splitterを入れると良い。
  • 外観が気に入らない貴方は、Material Theme UI を入れると気にいるかも。
  • ボクはMaterial Themeは行間がちょっと広くて気に入らなかったので、アイコンだけカッチョ良くしたくて Atom File Icons IDEAを入れてます。

みたいな感じです。参考にしてみてください。

コマンド履歴を検索する

by @kosappi_

bashzshCtrl + R を打つと、コマンド履歴を検索できます。 もはや常識のように感じてますが、無いと困る、という機能。 ss.gif (1.6 MB)

anyenvでいろんな言語の環境を一括管理

by @kokuyouwind

Rubyの環境はrbenvで管理してる人が多いと思います。 同じようにNode.jsの環境管理にndenv、Pythonはpyenv……と、この手の実行環境管理ツールは言語ごとに増えていきますね?

そうなると…… まぁ、.bashrcなどの初期化スクリプトはこうなりますよね。

# rbenv
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

# ndenv
export PATH="$HOME/.ndenv/bin:$PATH"
eval "$(ndenv init -)"

# pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"

はい。 初期化スクリプトが汚れるだけではなく、環境更新もいちいち個別にGit Pullが必要です。

こんなときにanyenvを使うと、*envを一括して管理してくれます。

# .bashrcには以下の2行だけを書けばいい
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"

# *envコマンドをinstallできる
$ anyenv install rbenv
$ anyenv install ndenv
$ anyenv install pyenv

# プラグインを入れると、*envをまとめて更新できる
# (anyenv自身も含む)
$ anyenv update

ちなみに、現在入れられる*envは以下の通りです。

$ anyenv install -l 
Available **envs:
  crenv
  denv
  erlenv
  exenv
  goenv
  hsenv
  jenv
  luaenv
  ndenv
  nenv
  nodenv
  phpenv
  plenv
  pyenv
  rbenv
  Renv
  sbtenv
  scalaenv
  swiftenv

これだけ色々な言語(と一部ビルドツール)が簡単に入れられて、バージョンも切り替えられるのは便利ですね。 brew派のみなさんも、試しに使ってみてはいかがでしょうか。

RubyMine はじめました ~ From Vim to RubyMine ~

こんにちは、id:eitoball です。

この記事は、Misoca Advent Calendar 2017 の21日目の記事です。

やっと、Amazon.co.jp から、

Echo の招待者に選ばれました。

というメールがきました!もちろん、購入しました。ちょっと早いクリスマスプレゼントです。

はじめに

Misocaの開発環境2017冬Misocaの開発環境 で、

普段どのエディタ/IDEでコード書いてる?

*  (neo)vim

と回答していたのですが、ここ10日間ほど RubyMine を使ってコードを書いています。vim や neovim など vim 系のエディタを20年以上愛用しているのですが、RubyMine でコードを書くようになった経緯を書いていきたいと思います。

実は、6年前から所有していました…

f:id:eitoball:20171220094558p:plain

最初は29ドルとかだったんですね…最初に購入したのは正式リリースの前でセール価格だったと思います。今まで、ろくに使わずにお布施だけしていました…

新しいバージョンが出るたびに使ってみていたのですが、最初は rvm とか rbenv に対応していなかったり、ターミナル上で操作すると同じように git とかの他のツールにアクセスするのが大変だったので、半日程度ですぐ諦めていました。

ヨーヨーでつられた

今年の9月に広島で開催されたRubyKaigi2017 にて、JetBrains さんがスポンサーをしていてブースを出されていました。*1

ヨーヨーももらいにブースへ行った際、「驚愕するデモ」*2に感動して、もう1回使ってみようかなぁという気持ちになりました。単純ですね…

Vim/Neovim に不満はあるのか?

全くないです。Sun OS で vi を使い始め、Vim、そして、Neovim と vi 系のエディタをメインの開発用エディタとして愛用し続けています。プラグインはとても充実しており、基本的な開発は Neovim 上で完結することができます。git などの CLI なプログラムも特に不満無く使うことができています。

ただ、 First 10 minutes of TDD intro episode 1 (unedited)Refactoring in IntelliJ IDEA, Live by Robert C. Martin (Uncle Bob) を見て、Kent Beck や Bob Martin が、さっそうと Eclipse や RubyMineを使いこなしながらリファクタリングしているのを見るとアジャイルな開発者を目指すものとして同じようにモダンな IDE を使いこなせるようになりたいなぁと思い続けてはいました。

RubyMine ことはじめ

いつも諦めるのは普段やっていることと同等なことができないのがもどかしいためだったので、新しい Rails プロジェクトで使ってみることにしました。気をつけたのは、可能な限りショートカットを使って操作することでした。最初は、この "Mastering RubyMine keyboard shortcuts" を読みながら進めるようにしました。この記事で紹介されている Key Promoter X というプラグインはある操作をするときショートカットが使える場合は提案してくれるのでやり直せる場合は元に戻して、提案されたショートカットを使うようにしました。リファレンスカード公式日本語版)は、常に開いていつでも参照できるようにしておきました。

Qiita にて RubyMine のタグから、ショートカット関連の記事を探して参考にさせて頂きました。

まず、使うようにしたショートカット(Mac OS X 10.5+)は以下の3つでした。

  • Shift+Ctrl+A - Find Action... (アクションの見つける…)
  • Ctrl+v - VCS Operations Popup... (バージョン管理の操作のポップアップを表示…)
  • Shift+Command+F Find in Path... (指定したパスから検索する…)

一番、重宝していたのは「Find Action...」です。こういうことがしたいと思ってショートカットが分からないときは、とりあえずこれで探すようにしていました。ここで git fetchgit rebase などの操作が ターミナルに戻らなくても、RubyMine 内でできることを知り、もどかしさが一気になくなりました。

本格導入

このように少しずつ操作を覚えながら、週末に簡単な Rails アプリを作って、一通りの事を RubyMine 上でできるようになったので、仕事での開発でも使うようにしてみました。

まずは、心機一転するため、レポジトリ内の .idea~/Libraries/Application Support/~/Libraries/Preferences 内にある設定ファイルといった関連ファイルを全部、削除して初期状態から使うようにしました。

あと、以下の3点を気をつけたのは以下の3点でした。

spec をショートカットで実行する。

仕事では、テスト駆動開発をするように努めています。テストを常に1キーストロークで実行できるのは、僕にとってとても重要なことです。最初、Alt-Ctrl-R で spec を実行して、同じ spec を実行するときは、 Ctrl-R で実行しています。

IdeaVim プラグインを使わない。

IdeaVim では基本的な Vimキーバインドしか対応していません。僕は、vim-surround や vim-unimpaired、fugitive などのプラグインキーバインドを多用しているので、Vimキーバインドを使っていると反射的にプラグインキーバインドを押してしまうので RubyMine では初期状態で推奨されている Mac OS 10.5+ (Mac OS Xの場合)を使っています。最初は、もどかしさもありましたが、Alt-上矢印 での Extend Selection や Alt-Shift-上下矢印 での Move Line Up/Down などのショートカットを使うようにして、RubyMine での編集方法に慣れていきました。

RubyMine の Terminal を使う。

どうしても、ターミナルでコマンドを実行したいときは、iTerm 2 などターミナルプログラムを開かず、Alt-F12 で内蔵のターミナルを使うようにして、RubyMine からできるだけ離れないようにしました。編集に戻るときには、Shift-Esc や Shift-Command-F12 を使っています。

現在の状況とこれから

現在まで、1週間程度使い続けて、仕事の開発などメインで RubyMine を使っていこうかなぁと思っています。Ctrl-V でのポップアップから作業用のブランチの作成して、Alt-Ctrl-R や Ctrl-R で spec を回して、都度、Command-K でコミットして、最後に Command-Shift-K でレポジトリへのプッシュまで RubyMine で滞りなくできるようになっています。最近はリファクタリング機能やデバッグ機能を積極的に使うようにしています。

Live Edit 機能JavaScript のデバッグ なども試していたいと考えています。Ruby/Rails での開発のほとんどを RubyMine で完結するようにしたいなぁと思っています。


First 10 minutes of TDD intro episode 1 (unedited)


Refactoring in IntelliJ IDEA, Live by Robert C. Martin (Uncle Bob)

*1:ちなみに弊社、株式会社Misoca もスポンサーしていました。

*2:Live Edit 機能のデモを見せて頂きました。

Rails 5.2 の足音 ~ Active Storage を試してみる ~

こんにちは、 id:eitoball です。

この記事は、Misoca Advent Calendar 2017 の15日目の記事です。

Rails 5.2 は、beta1 と beta2 が出てきて、正式なリリースも近々のようですね。皆さん、更新の準備はできていますでしょうか?今回は、Rails 5.2 の 目玉機能の一つである Active Storage を試してみようと思います。

Active Storage とは?

Active Storage makes it simple to upload and reference files in cloud services like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage, and attach those files to Active Records. Supports having one main service and mirrors in other services for redundancy. It also provides a disk service for testing or local deployments, but the focus is on cloud storage.

Active Storage は、AWS S3 や Google Cloud Storage などクラウドストレージサービスへのファイルをアップロードをするための機能です。 carrierwavepaperclip といった gem と同じような機能を提供します。 Rails 標準なので、モデルとの連携がシームレスに行うことができるのが特徴だと思います。

Active Storage を試してみる

今回は、Active Storage プロジェクトの README.md に記載されているように User モデルに avatar という属性でファイルを添付するようにしていきます。添付したファイルは、 AWS S3 に保存するように設定したいと思います。

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

はじめに rails gem (5.2.0.beta2) を追加します。今回は、せっかくなので、2017年12月25日にリリース予定の ruby 2.5.0dev を使用します。

$ ruby -v
ruby 2.5.0dev (2017-12-14 trunk 61215) [x86_64-darwin16]
$ gem install rails -v 5.2.0.beta2
…
Fetching: rails-5.2.0.beta2.gem (100%)
Successfully installed rails-5.2.0.beta2
28 gems installed

サンプルのアプリケーションを作成します。Rails 5.1 からの更新を想定したいので、--skip-active-storage で、後から、Active Storage を追加するようにします。*1

$ rails new --skip-active-storage -S --webpack=vue sample-application
…
* bin/rake: spring inserted
* bin/rails: spring inserted

作成したアプリケーション内に移動して、Active Storage をインストールします。config/application.rb 内で、 require "active_storage/engine" の行がコメントアウトされているので、コメントを外して、bin/rails active_storage:install を実行します。

$ cd sample-application
$ nvim config/application.rb
...
$ bin/rails active_storage:install
Copied migration 20171214014543_create_active_storage_tables.active_storage.rb from active_storage

データベースを作成して、マイグレーションを実行します。

$ bin/rails db:create db:migrate
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
== 20171214014543 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs)
   -> 0.0013s
-- create_table(:active_storage_attachments)
   -> 0.0014s
== 20171214004543 CreateActiveStorageTables: migrated (0.0028s) ===============

active_storage_blobsactive_storage_attachments というテーブルが作成されました。これらのテーブルにファイルのメタ情報などが記録されるようですね。

開発用サーバーを実行して、アプリケーションが動作することを確認します。

$ bin/rails server -b 0.0.0.0

ブラウザで、http://localhost:3000/ にアクセスして、”Yay! You’re on Rails!” と表示されていれば、インストールが成功しています。確認できたらサーバーは停止しておきます。

ユーザーモデルの作成

User モデルと関連するコントローラやビューを scaffold を使って作成します。あと、マイグレーションを実行します。

$ bin/rails generate scaffold user name:string address:string
      invoke  active_record
…
      create    app/assets/stylesheets/scaffold.css
$ bin/rails db:migrate

app/models/user.rb を編集して avatar 属性(has_one_attached :avatar)を追加します。

class User < ApplicationRecord
  has_one_attached :avatar
end

新しく追加した avatar 属性を表示したり保存したりできるようにします。

app/views/users/show.html.erb には、13行目あたりに次の行を追加します。

<% if @user.avatar.attached? %>
  <p>
    <strong>Avatar:</strong>
    <%= image_tag url_for(@user.avatar) %>
  </p>
<% end %>

app/views/users/_form.html.erb には、24行目あたりに次の行を追加します。

<div class="field">
  <%= form.label :avatar %>
  <%= form.file_field :avatar %>
</div>

最後に app/controllers/users_controller.rb では、72行目あたりを以下のように :avatar を追加します。

def user_params
  # params.require(:user).permit(:name, :address)
  params.require(:user).permit(:name, :address, :avatar)
end

開発用サーバーを立ち上げて、http://localhost:3000/users/new にアクセスして avatar のフィールドが追加されていることを確認してください。

f:id:eitoball:20171214130815p:plain

AWS S3 サービスの設定

ファイルを AWS S3 へアップロードするための設定を行います。Rails 5.2 では、秘密にしたい設定情報を暗号化することができるようになりました。AWS の認証情報はその機能を使って保存します。

bin/rails credentials:showconfig/credentials.yml.enc 内に保存されている情報を見ることができます。

$ bin/rails credentials:show
# aws:
#  access_key_id: 123
#  secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: abc123

bin/rails credential:edit で編集します。aws: からの部分のコメントを外して、AWS のアクセスキーIDとシークレットアクセスキーを記載します。EDITOREmacsVim などをコンソールベースのエディタを指定して編集して下さい。

$ EDITOR=nvim bin/rails credentials:edit
…
$ bin/rails credentials:show
aws:
  access_key_id: 123
  secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: abc123

Active Storage のストレージの設定は config/storage.yml に記載します。ここに AWS S3 の情報を追加します。amazon: からの行をコメントアウトして regionbucket を適宜修正して下さい。

$ nvim config/storage.yml
…
$ cat config/storage.yml
…
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: active_storage-test
…

そして、 config/environments/development.rb を編集して、開発環境で、AWS S3 ストレージを使うようにします。

$ nvim config/environments/development.rb
…
$ cat config/environments/development.rb
…
  # Store uploaded files on the local file system (see config/storage.yml for options)
  config.active_storage.service = :amazon
…

最後に aws-sdk-s3 gem を Gemfile に追加して、bundle install します。

$ nvim Gemfile
…
gem ‘aws-sdk-s3’
$ bundle install
…

開発用サーバーを起動して、http://localhost:3000/users/new にアクセスして実際にユーザーを作成して画像をアップロードします。

$ bin/rails server -b 0.0.0.0
=> Booting Puma
…
Use Ctrl-C to stop

f:id:eitoball:20171214130606p:plain

大きい画像をアップロードするとこのようになってしまいます。ですので、縮小できるようにします。

app/views/users/show.html.erbavatar 画像を表示している部分を変更します。

<% if @user.avatar.attached? %>
  <p>
    <strong>Avatar:</strong>
    <%= image_tag url_for(@user.avatar.variant(resize: '128x128') %>
  </p>
<% end %>

#variant には他にも色々な変換ができるようです。詳しくは、https://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/variant.rb を参照して下さい。

Gemfile を編集して、 mini_magick を追加して、bundle install します。*2

$ nvim Gemfile
…
gem ‘mini_magick'
$ bundle install
…

サーバーを再起動して、 http://localhost:3000/users/11 の部分は、先ほど作成したユーザーのIDです)にアクセスすると画像が縮小されていることがわかります。

f:id:eitoball:20171214130609p:plain

さいごに

今回は、近々リリース予定の Rails 5.2 での新しく導入される Active Storage を使って、ファイルを AWS S3 へアップロードするようにしてみました。今回は試していませんが、Google Cloud Storage などの他のクラウドストレージサービスやローカルファイルシステムにもアップロードしたりもできます。また、複数とストレージに同時に保存(mirroring)もできるようです。また、画像以外にも動画やPDFを扱うこともできるようです。

正式にリリースされていないため文書などが少なく、 carrierwave や paperclip と比べると機能はまだ少なく導入・移行は大変そうです。しかしながら、Rails の他の機能とシームレスに連携できるのは、とても魅力的だと思います。

明日、16日目は、merotan ( @renyamizuno_ ) が、HTML と CSS を使って究極の何かを作ったことについて語ってくれるそうです。

*1:webpacker を使っているので yarn が必要です。

*2:別途、ImageMagick をインストールしておく必要があります。

🔥カンバンを完了させるということ

こんにちは、mzpです。 Misoca Advent Calendar 2017 の13日目の記事を書きます。

🔖Misocaのカンバン

Misocaでは、各プロジェクトごとに付箋が作られ、壁に貼っていた。台紙となっている模造紙のことを名古屋ではB紙と呼ぶので、「MisocaのB紙」と呼んでいた。

f:id:mzp:20171212170223p:plain

名古屋オフィス外で働いている人と情報共有が難しかったため今はTrelloに移行している。

f:id:mzp:20171212132922p:plain

🚀完了したプロジェクト

完了したプロジェクトは場所でまとめて管理していた。 Doneの杜と呼んでいた。最初は「いっぱい終わったなー」と満足して見ていたが、だんだんと片づけたい気持ちが増してきた。

f:id:mzp:20171212133328p:plain

出雲大社への奉納

ちょうどその時期にRubyWorld Conference 2017のために島根に行くことが決まっていたので、出雲大社に奉納できないかと思って調べてみた。

FAQを確認すると

古い御神札・御守をお返しされる場合、境内に納め所がありますので、そちらにお納めお返し下さい。焼納祭を奉仕いたし、お焚き上げをさせていただきます。

と書いてあった。 念のため御札以外の紙でもよいかと問合せてみたが、問題ないとのことだった。

さっそく出雲まで持っていくことにした。

🐾奉納までの様子

はがす様子。

f:id:mzp:20171212134022p:plain

飛行機での移動。

f:id:mzp:20171031013943j:plain

RubyWorld Conference 2017に参加。

f:id:mzp:20171031025021j:plain

出雲大社への移動。

f:id:mzp:20171103040706j:plain

納める場所があった。

f:id:mzp:20171103042234j:plain

投入。

f:id:mzp:20171103042330j:plain

💗所感

  • 壁がすっきりしてよかった。
  • ただの付箋だが、それなりに苦労したプロジェクトばかりなので、ゴミ箱に捨てるのは偲びなかった。奉納する、という儀式をすることで、自分の気持ちと折り合いをつけることができた。
  • スピリチュアルエンジニアリングのための徳も高めることができた。

🏢採用

Misocaでは松江で働きたいソフトウェアエンジニアを募集しています。

Misocaの開発環境2017冬

はじめに

こんにちは、Misoca開発チームの洋食(yoshoku)です。

この記事は、Misoca Advent Calendar 2017 の8日目の記事です。

さて、Misocaでは、PCやエディタなど、開発環境を自由に選択することができます。 今回は、開発チームメンバーの開発環境を、一問一答形式で紹介したいと思います。

めろたん(@renyamizuno_)

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

  • Visual Studio Code
    • 最高。
  • Atom
    • teletype を試し始めて、最強。
    • 神ってる。
  • vim
    • たまにちょろっと直したい時にエディターに戻るのが面倒な時にサッと使ったりする。

好きなキーバインドは?

  • vim
    • ただ最近はエディターのキーバインドとぶつかったりしてなんか上手く使えないことが多々あるので、抜いてる。

お勧めのツールは?

黒曜(@kokuyouwind)

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

  • IntelliJ IDEA
    • コードジャンプとかリファクタ機能が超便利
  • emacs
    • ちょっとした実験スクリプトを書くときとか、サーバ上作業とかではこっち

好きなキーバインドは?

お勧めのツールは?

  • Database tool window
    • IDE内でレコードを確認したりSQLを書いて実行したりできるので便利
    • 設定すればport forwardしたりHeroku Postgresに繋いだりもできる
    • adapterも充実してるので大体のデータベースに繋げる(MySQLとPostgresくらいしか使ってないけど)
  • Railways
    • RailsのroutesをIDE内で確認できるようになる
    • Quick Navigationも入るので、~_urlみたいなのを打つのがすごく楽になる

ころさん(@corocn)

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

好きなキーバインドは?

お勧めのツールは?

  • IntelliJのサブツール群
    • 使ってみると意外と便利で Terminal, DB, VCS(Git), Debugger等にお世話になっている
  • Karabiner-Elements
    • これがないと生きていけない

他に何かこだわりは?

  • IntelliJはあんまりカスタマイズせずに使ってます。IdeaVimも入れましたが、しっくりこなくてやめてしまった。(既存のショートカットとconflictする部分が辛かった)

@sunflat

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

  • RubyMine

好きなキーバインドは?

お勧めのツールは?

  • RubyMine + IdeaVim
  • Karabiner-Elements
  • Clipy

他に何かこだわりは?

  • 普通のテキストはMacVimで書いてます
  • JISキーボードでIdeaVimを使うと、Ctrl+[ をESCとして扱ってくれないので、Karabiner-Elementsでそのように設定してます

@eitoball

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

  • neovim

好きなキーバインドは?

お勧めのツールは?

  • Alfred、Dash、MacBreakZ、Bartender、f.lux、hammerspoon

他に何かこだわりは?

  • できるだけ、マウスを使わないように努力しています。

@enda531

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

好きなキーバインドは?

お勧めのツールは?

@hidakatsuya

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

好きなキーバインドは?

お勧めのツールは?

  • Atom Package だと go-to-definition, ruby-test, vim-mode-plus, cursor-history, linter-rubocop, teletype あたり
  • iTerm, tmux, Pixelmator, Karabiner-Elements

@y0shoku

メインの開発マシンは?

普段どのエディタ/IDEでコード書いてる?

好きなキーバインドは?

  • vim、キーボードは英字配列です

お勧めのツールは?

  • bash-it、tmux、Sequel Pro、Jupyter Notebook

他に何かこだわりは?

  • マウスではなくトラックボール使ってます。
  • 机の上をスッキリさせたいので、できるだけ無線のものを選んでます。

おわりに

たまたま、アンケートに回答したメンバーが全員Macユーザーでしたが😅Thinkpadを愛用しているメンバーもいます👍 二年前のアンケートと比べてみると、時代の変化を感じられるかも⁉️

tech.misoca.jp

Misoca Advent Calendar 2017、明日の担当は @toyoshi です。

採用

Misocaでは開発者を募集しています。