ボクココ

個人開発に関するテックブログ

Heroku x Rails のサービスを本番運用する際に確認したいこと

ども、@kimihom です。

私は Heroku に Rails サーバーを立ててサービスを運用している。これまでの経験を元に、定期的にチェックしておきたい指標とか項目をまとめてみる。今後のサービス開発などで参考になれば幸いだ。

サービス構成

現在の構成はというと、以下のような感じである。

  • Ruby 2.4.1 (執筆時点で最新)
  • Ruby on Rails 4.2.8
  • Heroku Standard 1X Dyno * 4
  • Heroku Postgres Standard 0
  • Heroku Redis Premium 0

もちろん他にも使っているのはいろいろあるけど、ベースは上記のように至って標準な作りになっている。これによってインフラ周りでトラブルが起きることを最小限にとどめている。今現在でもインフラ周りで特別に問題になっていることはないので、これからも 上記の構成を使い続けていく予定だ。

では上記のような環境の中で確認したいことについてまとめてみる。

Heroku のメモリの項目をチェック

まずはサービスがメモリを使い過ぎていないかを定期的にチェックしよう。Professional Dyno にすれば、Heroku 内で "Meterics" の項目が見られるようになる。

f:id:cevid_cpp:20170505214402p:plain

ここでたまに線がガクッと下がっているのは Heroku が1日1回、自動で再起動されるためだ。この時にメモリは一旦リフレッシュされ、ちょくちょく溜まってたメモリを落としてくれる。この1日一回の再起動があるから、 Dyno を 2つ以上に保っておかないと、その一瞬はユーザーがアクセスできない時間ができてしまう。常にアクセスできるようにするために、そして 1つ Dyno が落ちても問題ないように、基本的に本番環境では Standard Dyno を2つ 常時起動にしておいた方がいいだろう。

さて、この図の上限の 100% を超えてしまうと、スワップ領域(上図中の下部紫エリア)にメモリを退避するようになり、めちゃめちゃレスポンス速度が遅くなるのでサービスのパフォーマンスに深刻な影響を及ぼすことになる。てことで メモリが 100% を超えないか、定期的にチェックしておく必要がある。ちなみに 100% を超えると、 Heroku のログに大量の R14 ログが吐き出される。

じゃあどうやってそのメモリを低く保てばいいのかってのが、Heroku のブログで丁寧にまとめられているので、これは必ず一読しておこう。ちなみに色々やって一番効果的なのは、定期的な Ruby のアップデート だった。

devcenter.heroku.com

上記の記事を元に記事を書いたこともあるので、上記ページの英語が嫌いな人は見てみるといいかもしれない。

www.bokukoko.info

Heroku のスループットとレスポンスタイムをチェック

同じく Heroku の Metrics でスループットとレスポンスタイムをチェックしよう。

これは例えば、あなたの運営するサービスが "夕方の15時にピークタイムを迎える" などの傾向を把握する上で必要になる。ピークタイムで例えば秒間50アクセスとか来ると、同時に全てのアクセスを処理できないのでリクエストの一部は待たされることになる。当然そうなると Metrics のレスポンスタイムがその時間に上昇するので、これは何か対策せんといかんな、という具合に管理することが可能だ。

ほとんどの場合、これは Dyno を増やすことで対応が可能だ。ただ、ずっと Dyno を増やしっぱなしにするのはお金が勿体無い。深夜帯なんてほとんどアクセスがこない場合がほとんどだと思う。そんな時は Process Scheduler などのアドオンを利用しよう。ピーク帯のアクセスはほとんど決まっていて、その時間に Dyno を増やせばいいと大体把握している場合は Process Scheduler は便利だ。これが例えばピーク帯が予想できないようなサービスの場合は、Adapt Scale などのアドオンを検討することになるだろう。

Rails のメトリクスは Scout がオススメ

Rails アプリ側のメトリクスツールは、 先ほどの Heroku ブログにも紹介されている Scout がオススメだ。NewRelic よりも軽く、より Rails に特化して表示してくれる。

どのリクエストに平均どのくらいのレスポンス時間がかかっているのかを簡単にチェックすることができる。どこから改善していけばいいのかがすぐにわかるので、Rails アプリを本番運用する際にはメトリクスツールは必須になる。

Heroku の メモリのチャートを眺めていると、たまにヒョンっとメモリが急上昇することがある。これは Rails アプリでたまに生じる Memory Broat と呼ばれるもので、特定のコードが無駄な処理(例えば N+1 のクエリ) を実行することで処理に多くの時間を費やしてメモリが急上昇するものだ。この場合は Rails のソースコードを修正する必要がある。その具体的な方法は、Scout のブログを参照していただきたい。もしくは先ほど紹介した "Heroku on Rails アプリのメモリ増加対策の方法" にもちょろっと紹介してある。

Scout のフリープランは割とすぐにリミット行っちゃってすぐアップグレードしろってメールくるのでそこは注意。

Heroku Postgres や Redis もたまにはチェック

基本的に Scout のメトリクスで DB 周りの大体のことも把握できるのだけども、それ以外でチェックしないといけないこともある。

特に Heroku Postgres はプランによって色々と制限があるので、その制限を超えていないかを定期的にチェックしないといけない。

Heroku Postgres の Standard-0 の場合、コネクション数の上限は 120 だ(これを超えるってことはほとんどないとは思うが)。また、ストレージの上限は 64GB である。まぁ Standard-0 にアップグレードすればほとんどのサービスでは当分困ることはないとは思うが、予期せぬ事態に陥らないように、定期的に Heroku Postgres のページにもアクセスするようにしたいところだ。

Heroku Postgres のページでも遅いクエリを発行しているものが何なのかを教えてくれたりするので、 Scout の結果と合わせてどれを直さないといけないのかを確認するようにしよう。

Heroku Redis も有料プランにあげればほとんどの場合問題になることはないとは思うが、定期的にメモリや接続数を使い過ぎていないか等を見に行くようにしよう。 Redis の初期設定はちょっと注意が必要なので以前書いた記事を紹介しておく。

www.bokukoko.info

最後は安定の Papertrail

もはや Heroku を使っている方にとってはスタンダードとなりつつある Papertrail

Papertrail のアラート機能を使って、エラーが起きたら迅速に Slack 等に通知する仕組みを用意しておこう。例えば Papertrail の検索条件を "Error" AND -"RoutingError" で保存し、アラートで "Error" の検索がヒットした時に Slack に飛ばすようにしよう。

これでアプリケーションレベルのエラーをすぐに検知することが可能だ。

それ以外にもアプリケーションログで重要なイベントは何でも通知できるようにしておくと、ユーザーの動向に基づいた素早い行動ができるようになるのでじゃんじゃんセットしておくといい。これはお金を払ってでも使っていきたいサービスだ。

終わりに

以上が私が Heroku を本番運用している中で定期的にチェックしている項目だ。一部は以前紹介したことのある Tips ではあるが、改めて全体をまとめとして紹介した。

Rails のレールと Heroku のレールに乗れば、Web サービスを極少人数で運用できる体制が実現できる。

最後に Heroku に興味を持った方は、ぜひ Japan Heroku User Group にジョイン!

ライブラリの利用を減らしていくことの重要性

ども、@kimihom です。

最近の運用フェーズでの開発で意識していることの一つ、「Gem ライブラリの利用を減らす」ことについて思うことを書く。 記事の内容は Ruby 周りに最適化されているけど、他の言語でも同様のことが言えると思うので適宜置き換えて読んでいただきたい。

初期フェーズによるライブラリの利用

新サービスを作る段階では、「いかに早く機能を作り、検証しながら機能を作り直していくか」が大事になってくる。その時にいちいち機能をゼロから自分で作っているようでは時間の無駄だ。第三者が作ってくれた、ライセンス的に問題ないライブラリをシステムに組み込み、作っては壊しての繰り返しで機能検証していくことが大事になってくる。サービス開発初期でライブラリを使う理由は「機能を素早く実現するため」にある。だからちょっとした機能でも Gem で入れまくることになる。

これは全く問題ない。むしろ推奨されることだと思う。開発スピードを強みすることが第三者(特に大企業)と差別化する上で重要になる。小規模チームでの小回りの速さは確実に武器になる。

プロダクトマーケットフィット後のプロダクト

しばらくして見事サービスがプロダクトマーケットフィットの段階になれば、今度はサービスを集中して磨き上げることが大事になってくる。そこではより確実に素早くソースコードを改善していくことが求められる。

わけがわからんが、なんとなく動いている。” そんな状態を少しずつ無くしていこう。例えば以下のような時に役立つ。

サービスの最適化に役立つ

基本的にライブラリは、あらゆる利用を想定した作りになっているため、カスタマイズ項目がたくさんある。そしてそのぶん、ソースコードは Fat になり複雑になる。ライブラリの機能がさほど複雑なロジックを必要としない場合には、自前で実装することで無駄な処理を実行することがなくなる。より速く効率的な実行速度を実現でき、今後の独自の拡張性を見込める機能を実現することができる。

独自の拡張性は、今後のサービスの差別化に役立つ。プロダクトマーケットフィットの段階以降は、サービスに最適化された機能を多く増やしていくことが大事になってくる。競合が出て来ても、簡単には真似できないようなサービスをコツコツ実現していくのだ。

まずはマイナー系のライブラリから最適化することをお勧めする。そのようなライブラリは基本的に自前でも十分実装できるからマイナーなままであるパターンが多いからだ。 ちょっとした実装で実現できそうな Gem ならわざわざ使わずに自分で作った方が適したものになる可能性が高い。

反対に視点を変えるとライブラリを使い続けることで、Gem 自体がコミュニティの力でどんどん進化していくという側面がある。てことでライブラリを使用する/しないの見極めが必要だが、まずはほとんどアップデートの無いライブラリから削除することを検討するようにしている。

起動時の使用メモリを省略できる

起動時に大量のライブラリを読み込むと、そのぶん大量のメモリを必要としてしまい、無駄にサーバーリソースを消耗することになる。ライブラリを減らさずに増やし続けてしまうと、それがいつか限界を迎えて Out of Memory のエラーが発生することがある。

使用メモリを把握するには、Derailed Benchmarks などの Gem をインストールして調査してみよう。あまり使っていない Gem が案外無駄にメモリを消耗していたりする。そういうのは優先的に外していって自前で実装していくようにしよう。

GitHub - schneems/derailed_benchmarks: Go faster, off the Rails - Benchmarks for your whole Rails app

Gem のほとんどの機能は使わないけど、どうしてもその Gem を使わないといけないような場合、 require するものを最小限にとどめることで対応が可能だ。例えば、 rack-cors を入れる時には require で読み込むものを限定している。以下ような書き方で、ライブラリの利用を最小限にとどめることができる。

gem 'rack-cors', :require => 'rack/cors'

こうしてより多くのアクセスを少ないサーバーリソースで運営することもできるようになる。そして何より、自分の理解している範囲でコードが動いているという安心感。問題が起きても自力でデバッグすることができるだろう。

独自実装でオープンソース公開の機運ができる

独自に実装した何かが第三者に公開できるようなものが出てくる場合がある。その時はコミュニティに貢献するチャンスだ。うまくライブラリ化して逆に公開しよう。そしてうまく実装してマーケティングもうまくいけばスター数がつくかもしれない。そのようなライブラリを持つことを増やすことがエンジニアの価値だと考えている方にとってはまさに理想的なオープンソースの公開方法ではないだろうか。

オープンソースで公開すると、どうしてもカスタマイズでオプションをたくさん作るようなことが必要になるかもしれないが、その方針を決めて作るのもコミッタであるあなた次第だ。そんな自由なオープンソース活動を実現することができる。

終わりに

改めて注意書きするけど、最初からライブラリの利用を減らすべきとは書いてはいない。あくまでプロダクトマーケットフィットを達成した後のサービスの最適化の段階でやっていくべきだ。だからサービス初期のエンジニアと、サービス成熟期のエンジニアの求められる役割は違う。

ライブラリの利用を減らして、独自の価値を持つサービスがどんどん増えていくといいなと思っている。

月額課金モデルの Web サービスの設計方法

ども、@kimihom です。

今回は月額課金モデルの Web サービスを実現したい企業向けに設計の参考になる情報を提供できればと思う。こういう情報は割と自分なりに設計して実装するっていうパターンが多いかと思うが、とても大事なことなので慎重に検討していこう。

決済サービスの選択

まずは決済サービスをどれにするかって話。ここで一番大事なのは、扱うカード提供会社の種類だ。 Visa, Master は当然として、その他のクレジットカード会社が使えるのかどうか。ここは顧客のカード登録の自由度を決めるので、実は決済手数料よりもよっぽど大事な項目になる。要チェックだ。

あとは企業によっては収益が出た後の支払いフローも確認しておいたほうがいいかもしれない。収益の確定はいつで、支払いはいつなのか。黒字倒産するほど急成長することは稀だとは思うが、そのあたりのキャシュフローも事前に把握しておく必要がある。

あとは最低限クレジットカードの登録と、そのカード情報をトークン化して決済ができる仕組みがあれば大丈夫だ。

最終的にどのクレジットカード決済サービスを使うべきかは自らの意思で判断していただきたい。

決済フローの設計

さて、月額課金モデルと一口に言えど色々な方法が存在する。以下のようなバリエーションを考えなければならない。

有料プランは単一か複数か

当然単一の課金プランであればシンプルで実装しやすい。途中のプランアップグレードを考える必要はないし、プランごとに機能を出し分けたりする必要もないからだ。

プランを複数用意するケースってのは、使って欲しいターゲットがそれぞれいて、そのターゲットに向けた特別な機能を上位プランでは提供したいという場合になるだろう。ということで、最初のローンチでは単一プランしかなかったとしても、今後利用の想定ユーザーが増えていくにつれて、単一プランから複数プランに変わることも十分にあり得る。だから単一プランを選んだとしても今後複数プランが出てきた時にどうすべきかはあらかじめ考えておいたほうがいい。

ひとまずデータベースには plan が作られ、id, price, name が最低限必要になるだろう。

毎月いつの決済となるか (ユーザーがアップグレードした日なのか、全ユーザーが每月末、每月初なのか)

いつのタイミングで決済するのがベストなのだろうか。代表的な2つの方法を紹介する。

まずユーザーが10日にアップグレードしたら毎月10日に課金が走るパターン。これはユーザーにとってわかりやすいし、料金の計算も毎月固定額だからイメージしやすい利点がある。ただし、ユーザーごとに決済の日時が変わってしまうので、運用する側は常に毎日何かしらの決済コードを走らせ続ける or API 側で実行しなければならない。これは例えばメンテナンスをしたいという時もとても慎重になる必要があったり、コードの修正などもリリース前とリリース後でユーザーに不備が出ないように慎重になる必要がある。つまり、この方法はよほどプランや料金体系が固定化されていない限り、やがて困難を伴うことになるだろう。

私のオススメは月末や月初に企業毎に逐次決済していく方法だ。これであれば、基本的に決済は毎月末だけ集中すれば良いのでメンテナンス的にも気持ち的にもありがたい。決済はできる限りシンプルにさせることでトラブルを防ぐことができる。ただこの方法の問題を挙げるなら、有料にしたその日から月末までの料金をどうするかという話だ。この場合、次回課金日時までの日割り料金を決済させるか、思い切ってそこは無料にするかのどちらかになるだろう。おそらくどのサービスもトライアル期間を設けるだろうから、そのトライアルの期間が 3か月みたいな長めに設定できるサービスであれば、初月は日割りをなくして無料にするという方法がいいかもしれない。トライアルが2週間で切れるようなサービスであれば反対に日割り料金で初月は決済するような流れになるだろう。

基本的にはユーザーには先払いの仕組みとなるだろう。ユーザーが料金を支払っていただいたら、その後の1か月もしくは1年使える権利を買ったことにする方法である。ただし、従量課金制にした場合にはそのようにはいかない。従量課金制の場合は前月いくら使ったのかを計算して、月末や月初でそれを請求するか、キャッシュフローを考慮してポイントとして購入していただくかどちらかの方法を選ぶことになるだろう。

うちの場合は月末に来月のシステム利用料と、当月の利用実費(従量) を足し合わせた金額を請求する実装にしている。

このように決済方法は今後どんどん変わっていく可能性があるから、決済サービスで提供される Subscription の仕組みはできる限り自前で実装した方がいいと思う。

私の場合、 bill_history テーブルを用意し、target_month, plan_id, price, charge_id, contract_id を指定している。特に大事なのが charge_id。決済に成功した場合に、その戻り値である charge_id を保存するようにしよう。これは後述する決済失敗の判断材料になる。

また bill_history にも price を入れているのは、プラン以外の毎月変動する合計としての金額をここに保存するためだ。例えばライセンス数に応じて料金が変わったり、アドオンを追加して料金が加わったり、従量課金を追加して料金が加わったり。そんなパターンを合計した金額を bill_historyprice に入れよう。

プランが複数の場合、ユーザーが途中でアップグレードした時にその決済をどうするか

有料プランから有料プランのアップグレードは地味に計算が大変だ。既に今月分の A プランを支払っていて、アップグレードしたらさらに B プランの料金も支払ってもらうことにしてしまうと、ユーザーは余計に料金を支払わなければならない。A - B の日割り額を差分として頂くか、来月初からプランアップグレードが適用になるかのどちらかの設計になるだろう。

来月初からプラン適用、という設計の場合、あらかじめ bill_historyに来月分のレコードを1つ追加してあげて、定期決済時に来月分の bill_history が既に作られていたら、そのプランでの料金を請求する実装にすれば良い。

プラン以外での課金が発生するか。その課金はどのタイミングで決済されるか

これは例えば毎月末に全ユーザーの決済をすると決めた場合、その他の決済が行われるタイミングも考慮する必要があるということだ。

例えばトライアルから有料へアップグレードした瞬間、その日から月末までの日割り料金を請求する場合はその時点で課金が発生する。またプランアップグレードで当日からプランのアップグレードを適用する場合にも日割り料金が発生するだろう。

従量課金制の場合、退会時にも既に使っていた料金分を請求する必要がある。

これらあらゆるパターンで決済が発生する可能性があるので、自社サービスに最適な決済フローを設計しよう。

決済に失敗した時にどのように対応するか

そして定期課金で最も厄介なのが決済に失敗した企業へのアプローチだ。

決済に失敗することは実は非常によく起こる。50社いたら2,3 社は毎月失敗すると考えてよい。その場合、即退会だとか使えなくするだとかはあまりに厳しすぎるので、一時的に支払ったことにして使える状態にしなければならない。

ここで先ほどの bill_history に保存した charge_id が活躍する。決済に失敗した場合は charge_id に値を保存できないので、charge_id が空の状態の bill_history が作られる。 月末課金だとしたら、 毎月 3, 8, 15 日に再決済のスケジュールを立てて、当月の bill_hisotrycharge_id が空のレコードを取得し、そこで保存された前月請求額の price を再決済するようにすれば良い。もし成功すれば charge_id を保存しておくということになる。

クレジットカード起因で決済に失敗した場合、対象ユーザーへカード変更の依頼を促すメールを送る実装をすれば、毎月の決済フローをほぼ自動化できる。最終トライの時にカード決済が失敗したら そのユーザーをどうするかってのはサービス次第で決めよう。経験上、3回リトライの仕組みを実装すれば、少なくとも2回目でほぼ全ユーザーの決済は成功する。3回目でも失敗する場合は明らかにその企業が退会を決意したくらいしか起き得ない。

月額課金を自前で作るか、Webサービスに任せるか

改めて月額課金の仕組みを自前で作るか Web サービス側に任せるかを検討したい。

まず自前で月額課金の仕組みを作るのは、実はさほど難しくはない (テストは大変だが)。多少の手間をかけて、今後のサービスの料金体系変更に強くさせるのは良いことだと私は考えている。決済に失敗した時の課金まで実装できれば、基本的に Web サービス側で提供する月額課金 (Subscription) の仕組みと同じものを作れる。

反対に Web サービス側で提供されている定額課金 (Subscription) の仕組みを使うべきはどんな時か。これは私の思うことに過ぎないけども、今後のサービスにおいてプラン変更や料金変更がほとんどなく確定されたものであり、かつその決済サービスが(どこかの決済サービスとは違って)残り続けるという確証が持てる場合は選択しても良いだろう。その条件を飲み込めば、月額課金の仕組みをとても素早く構築に、そして確実に実装できる利点が手に入れられる。また、年額決済のサポートなども決済サービスによっては対応しているところもあり、これらの仕組みをささっと導入できる魅力は大きい。自前で月額と年額をそれぞれ実装するのはなかなか大変だ。

両者どちらもトレードオフがあるので、最終的に決めるのは開発者自身である。

終わりに

月額決済の仕組みはしっかりと設計する能力が求められる。ビジネス的なキャッシュフロー、そしてそれに伴う決済のタイミングや料金の計算方法。どれも念入りにあらゆるパターンを考慮した上で実装していこう。

最近は各クレジットカード決済会社がテスト環境と本番環境を完全に分離して開発及びテストをしやすくさせてくれている。そのため入念にテストをすれば、自信を持ってユーザーに決済サービスを提供できることだろう。

これから月額課金モデルのサービスを作る方に有意義になれば幸いだ。

Ruby のバージョンを上げてGuard が動かなくなった時の対応

ども、@kimihom です。

Ruby で開発しているのであれば常に新しいバージョンで開発を続けたいもの。その中で今回は guard が動かなくなったのでその対応メモ。

  • Ruby 2.3.3
  • guard 2.14.1

エラー内容

こんなエラーが出て開発できなかった。

$ bundle exec guard

22:34:15 - INFO - Run all
22:34:15 - INFO - Running all specs
/Users/user/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler (LoadError)
    from /Users/user/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/user/dev/rails/rails4.2/myapp/bin/spring:8:in `<top (required)>'
    from bin/rspec:3:in `load'
    from bin/rspec:3:in `<main>'
22:34:15 - ERROR - Failed: "bin/rspec -f progress -r /Users/user/dev/rails/rails4.2/myapp/vendor/bundle/ruby/2.3.0/gems/guard-rspec-4.6.4/lib/guard/rspec_formatter.rb -f Guard::RSpecFormatter --failure-exit-code 2  spec" (exit code: 1)

まぁ Bundler 周りが怪しいよね、ってのはわかる。

対応ログ

Guardfile

- guard :rspec, cmd: "bundle exec rspec" do
+ guard :rspec, cmd: "bin/rspec" do

...

end

これで spring 経由で rspec が走るとのこと。そしたらこんなエラーが次に出た。

22:37:25 - INFO - Run all
22:37:25 - INFO - Running all specs
There is a version mismatch between the spring client and the server.
You should restart the server and make sure to use the same version.

CLIENT: 1.6.1, SERVER: 2.0.1

どうやら spring のバージョンが古いみたいなのでアップデート。

$ bundle update spring

そして…

$ bundle exec guard

22:38:43 - INFO - Run all
22:38:43 - INFO - Running all specs
Running via Spring preloader in process 28169
...............................................................................................................................................................................................................................

Finished in 13.06 seconds (files took 1.62 seconds to load)
XXX examples, 0 failures

よっしゃ!動いた。

得られた教訓

Gem はテストツールも常に最新に更新しておかないとね。それにしても、 bundler、こいつは優秀だな。

Rails の フロントエンド周りの未来予測

ども、@kimihom です。

Rails の SprocketsUglifier などが最新の JavaScript に追従していないという理由で、Rails 標準のやり方から外れて最新のフロントエンドツールを追い求める系の報告が多い。一部では完全に Rails の Asset Pipeline から外れて、Gulp などに移行する話もよく聞く。確かに現行の Rails のフロントエンド環境で開発すると、let や クラス構文をまともに使えない(エラーになる)ため、最新の構文に対応した JavaScript フレームワークはほとんど使えないのは大きな問題として残り続けている。

最新版である Rails 5.1 から、ようやく jQuery からの脱却とフロントエンド周りの最新化、つまり Yarn や Webpack の導入が検討され始めている。これに期待されている方も多いのではないだろうか。

Rails5.1に向けてフロントエンド周りで起こっている革命まとめ - Qiita

そもそもこんなにフロントエンドの話題が盛んな今、なぜ最新を行くはずの Rails はここまで遅いのだろうか。

CoffeeScript と Turbolinks

Rails としては、「CoffeeScript を使え」というのが答えのようである。これを使えばクラス構文など、既存の JavaScript で抱えていた問題をよしなに解決してくれる。

Rails としてはそれに Turbolink を組み合わせれば、SPA も作れるのだ。今までの Rails のレールはそこにあったのである。 Rails 5.0 でもその思想は変わらず、よりモバイルフレンドリーになった Trubolinks を推奨していた。

Rails5 が示したサービス開発の新しい指針についての考察。

本来であれば、私たちはこれらを使うべきだったと言えるし、Rails 5.0 までは CoffeeScript と Trubolinks の組み合わせが Rails の答えだったのだ。

Rails 5.1 で変わろうとする未来

かつて Rails がデフォルトの JavaScript フレームワークを prototype.js から jQuery に変えたように、Rails 5.1 からついにフロントエンドの最新に迫るようになった。これは最近のフロントエンドの流れに反応した結果だ。CoffeScript や Turbolinks ってのを Rails 5.0 までは推していた私も、Rails 5.1 からは標準ではなくなるのはほぼ間違いないと考えている。

ようやく対応が始まってきたのには大きな理由がある。現時点でのあらゆるブラウザが、 JavaScript の最新仕様に対応していないからである。Rails が最新の JavaScript に対応しようとすると、Babel など最新の JavaScript 仕様に対応できていないブラウザに対応するためのコンパイラが必要になってしまう。これらの煩わしさから解放されるには、ほぼ全てのブラウザがデフォルトで JavaScript の新仕様に対応してもらう必要がある。

Rails 5.1 が一般的に普及する頃(1, 2年後)には、この問題が解決されているだろう。だからこそ Rails は今このタイミングで最新の JavaScript 対応に着手し始めたと考えられる。

Rails エンジニアが今すべきこと

そんな中で Rails エンジニアはどう行動していけば良いのだろうか。

まずは Rails 5.1 に向けて、JavaScript の新仕様にはしっかりと追従していく必要がある。具体的には クラス構文, Promise, などの ES~ 系のJavaScript の新仕様, Web Component などの HTML5 などである。これらは React のような JavaScript フレームワークの仕組みではなく、ブラウザ標準のHTML仕様として今後普及していくものだ。これらをマスターしておき、Rails 5.1 に向けて備えておきたいところである。それらが一般的に普及すれば、プロジェクトによっては React っていらなくね?って話になる可能性もあるから、基本をまず抑えておくことは本当に大事なことだ。

大規模な SPA を作る必要がない場合、Rails 5.1 が一般的になるまでは jQuery Rails で全く問題ないと思う。Rails の form_for とそれに連動する値セット/検証や I18N の仕組みは一級品だし、jQuery のエコシステムは膨大だからだ。やがて jQuery 依存のライブラリは、純粋な JavaSciprt だけで書き換えられるようになっていく。そうなった時に、今の jQuery プラグイン縛りから解放され、jQuery からも外れられる。事実、 jQuery Rails は既に jQuery の依存をなくす実装が進んでいる。1, 2年後には jQuery を使う理由(クロスブラウザ)なんてのはなくなって、Query Selector API などの新仕様を使えば良くなるのだ。(jQuery はすべて置き換えられるってのを紹介している記事もある)そんな未来が 1,2 年後には間違いなくやってくる。

ちなみに現在の Rails のフロントエンドの仕組みがどうしても嫌だ!っていう場合や、フロントエンドとバックエンドを完全に分けたいという強いこだわりがある場合は、 Rails を Web API としてだけ使うやり方は大いに考えられる。だけども、そんなことするくらいならバックエンドを Rails にするって選択は無いなぁと思ってしまう。だったら Go とか Scala, Elixir とかの方がよくね?って話になるからだ。「サーバは API だけの作りにして、あとはフロントエンド(JavaScript / Swift / Kotlin)に全部やらせたい」って考え方の人は、他のフレームワークの方が要望を満たせると思う。適材適所でフレームワークの利用を検討すべき時が来ている。なんでもかんでも Rails ってのはやっちゃいけないパターンだ。

Rails は引き続き動的な HTML レンダリングが中心のフレームワークのままやっていくことだろう。.erb の世界である。スマホアプリもWebView 中心の作りにすれば、素早く修正を反映できて高速な開発が可能になる。

終わりに

私としては今後、スマホアプリは WebView 中心のものになっていく感が高まっていくと思っていて、Rails の方針には賛同している。ただしその障壁として iOS の HTML5 対応が遅いので、今後は iOS が従来の IE のような存在になっていくと考えている。となると、日本の iOS ユーザーの比率が高いということがネックになり、またもや日本だけ IE 対応をしていた時のように iOS 対応をしなければならない未来ってのを予測している。こういうのは Web エンジニアの宿命なのかもしれない。

何はともあれ今後の Rails と HTML5 界隈の話から目が離せない。

追記

はてぶコメントありがとうございます。しっかりと読ませていただき、良い気づきを得ることができました。

極める技術を絞るという勇気

ども、@kimihom です。

f:id:cevid_cpp:20161212224134j:plain

いつの時代も、新しいテクノロジーがどんどん出てくるものだ。「この技術は世界を変える!」だなんて言って、みんなが飛びついて徐々に一般化されていく。「とりあえずなんでも触ってみる」ってのはもちろん大事なことだ。それが自分に合うか合わないかを判断するためにも、常にアンテナを巡らせる必要がある。

オールラウンダーは学校教育では良いとされていた。一つ100点で他が30点の生徒より、全てが90点の生徒が優秀とされる。だがしかし、プロの現場に入るとこれが急転する。100点を一つでも持っている人の方が貴重になって価値が高まるのだ。優秀ではなく希少性ってのが評価されるのである。これって不思議なことだよね。教育ってのは社会に役立つように教育されるのに、実際に社会に役立つ人材ってのは教育での優秀な人材ではないんだもの。

さて私の場合はどうなのか、ちょっと書いてみようかな、といったところが今回の記事。

いろいろな技術に流されていた時代

私は以前まではいろんな技術が出てくるたびに、それに飛びつき熱中したものだった。そういう新しい技術に触って、ドヤるのはエンジニアとして誇らしいものがあった。そんな嬉しさも相重なり、気の赴くままにイケてる新技術に飛びついていたものだった。入り口まではドキュメントが整備されているので、それなりのレベルになるのは簡単だ。そこで学んだ新技術というよりかは入門者向けの記事を書くと、多くの読者に読まれてシェアされやすいということを理解した。

しかし、多くの技術に触れ続けていると、やがて気付くことがある。いろいろな技術イベントに登壇している人を見たときに、「はて、自分の"技術"と呼べるものはあるだろうか?」という問いである。これに自信を持って答えられないと感じた時、エンジニアとして自分はどうしていきたいのかを真剣に考えるようになった。

私はオールラウンダーになりたいのか、プロフェッショナルになりたいのか、という問いである。

そして見つけた私が極めたい技術

実は私の中で、新しく触った技術の中で「これはすっっっっっっっごい!」と思う素晴らしいものとめぐり合う時がたまにあった。 Ruby on Rails, Heroku, AngularJS, Twilio といったものがそうだった。そういう自分の中の感動や関心を突き詰めるのが、結局のところ自分のパフォーマンスを最大限発揮できるものだと信じ、私はこれらの技術にのめりこんだ。最終的に開発の方向性とかの問題で AngularJS は今では使わなくなってしまったが、他の3つを自分の武器として極めてみようと思ったのである。

その中で私は特に Twilio には最大限の協力をした。というのもコミュニティとしてまだ未成熟な時期であったし、勉強会などのイベント運営でも人手不足な感じな状態だったからだ。だから私は Twilio の勉強会には積極的に発表して自分の学んだ入門的なところから上級向けのところまで、あらゆることをコミュニティにシェアしていった。おかげさまで Twilio の東京の勉強会には必ず私が出てくるくらいになったし、密な情報共有することのできる素晴らしいエンジニアと出会うことができた。

そして Twilio を極めることや普及させることに躍起になっていた私に、また別のチャンスがきた。Twilio 経由で知り合った Heroku コミュニティのイベントで登壇する機会をいただいたのだ。そこで私は 7年以上使い続けている Heroku について熱弁した。今でも私は Heroku を超えるクラウドのプラットフォームは存在しないと思っている。新しいクラウドのインフラはどんどん出てくるけど、Heroku ほどシンプルなものはない。だから私は Heroku をこんなにも使い続けているのである。 その時の発表はとても嬉しく、気持ちの良いものだった。

極めた先に待っているもの

こうやって特定の技術を極め続けて普及活動を行っていると、思わぬチャンスにめぐり合うことができる。

Heroku の発表を通じて、日本の Salesforce 最大のイベント「Salesforce World Tour Tokyo 2016」の登壇が決まったり、

Salesforce World Tour Tokyo 2016 for Developers

Mashup Award の年末の大イベントである FESTA 2016 By MashupAwards で Twilio 代表として発表させていただくことになったりしたのだ。

FESTA 2016 By MashupAwards - connpass

どちらも、私が好んで使い続けてきた技術に関する発表なので、心の底から自分の思いを伝えることができる。そんな素敵な場にめぐり合うことができたのだ。これは、いろんな技術に手を出し続けて強みが何もなかったオールラウンダーな私だった頃では到底立つことのできなかった舞台であろう。

今週はそんなイベントが立て続けに待っている。私の 2016 年はこれからだ。

Rails assets 内の JavaScript のメソッドを View 内から呼び出す方法

ども、@kimihom です。

Rails で開発していると、assets/javascripts 内で定義したメソッドを View 内に書かれた <script>タグから呼び出したい時がある。Rails は基本的に assets/javascript 内のコードを全てひとまとめにして一つのapplication.jsってのを作るから、特定のページのロード完了後に特定の JavaScript コードを呼び出したい時にちょっと困ることになる。そんな時は View 内に <script>タグを入れる必要が出てくるだろう。

View 内と Assets 内の JavaScript の混在による課題

だが、View と Assets 内に JavaScript を混在させるといろいろな問題が出てくる。そう簡単にはいかない問題だ。

外部ライブラリの読み込みの前にメソッドを呼んでしまう

jQuery のような JavaScript ライブラリは、より早く HTML を表示させるために <head>タグではなく、<body>の一番下に書くことがあると思う。そうなると、レイアウト内の yield の後に jQuery が読み込まれることになる。つまり、View 内でベタ書きした <script> タグの方がライブラリよりも先に呼ばれてしまうことになる。これはよろしくない。


app/views/layouts/application.html.erb

<html>
<head>
  <title>Sample App</title>
  <%= stylesheet_link_tag    'application', media: 'all' %>
  <%= csrf_meta_tags %>
</head>
<body>
   <%= yield %>
   <%= javascript_include_tag 'application' %>
</body>
</html>


app/views/users/index.html.erb

<div id="users">
  .....
</div>
<script>
  $("#users")....   // <- "$" が呼び出せない!!
</script>

ソースコードのカオス化

View 内に <script> タグをどんどん入れて行ってしまったり、ロジックをその中にベタ書きしてしまうと、assets/javascripts にある JavaScript ファイルとごちゃごちゃになってメンテナンス困難なソースコードが出来上がってしまう。

だからできれば assets/javascripts 内に JavaScript のコードを集約させたい。

View から Assets 内の JavaScript を呼び出せない

かといって、assets/javascripts 内で functions を定義しても、Rails の AssetPipeline による JavaScript の Minify によってメソッド名を指定することができない。

app/assets/javascripts/users.js

function setUser() { 
  ......
}


app/views/users/index.html.erb

<div id="users">
  .....
</div>
<script>
$(function() {
  setUser(); // <- "setUser" が呼び出せない!!
});
</script>

content_fortrigger によって解決しよう

さて、本記事のメインテーマである解決策を掲示しよう。まずは1点目の <script>タグの読み込み順について。これは content_for を使うことで解決できる。

app/views/layouts/application.html.erb

<html>
<head>
  <title>Sample App</title>
  <%= stylesheet_link_tag    'application', media: 'all' %>
  <%= csrf_meta_tags %>
</head>
<body>
   <%= yield %>
   <%= javascript_include_tag 'application' %>
   <%= yield :footer %>
</body>
</html>


app/views/users/index.html.erb

<div id="users">
  .....
</div>

<%= content_for :footer do %>
<script>
  $("#users")....   // <- "$" が呼び出せる!
</script>
<% end %>

これで、 jQuery が読み込まれた後に、 <script> タグを読み込ませることができる。

続いて JavaScript の Minify によって指定のメソッドが呼び出せない問題。これは trigger を定義してあげよう。

app/assets/javascripts/users.js

$(function() {
  $(document).on("users:loaded", "#users", function() {
      //.....
  });
});


app/views/users/index.html.erb

<div id="users">
  .....
</div>

<script>
<%= content_for :footer do %>
<script>
  $("#users").trigger("users:loaded");
</script>
<% end %>

trigger には引数を与えることもできるので、とても柔軟に View と Assets の JavaScript を通信することが可能だ。

Rails の content_for と jQuery の triggerによって、個別 View のロード時に特定の JavaScript を実行することができるようになった。

終わりに

trigger はいろいろと応用が利くとても便利な jQuery メソッドだ。より詳しく知りたい方は以下の記事も参照されるといいだろう。

今更ながら jQuery の trigger の魅力について語らせてもらう

Rails のレールに乗った美しいコーディングを目指していこう。

独学での Web プログラミング学習まとめ

ども、@kimihom です。

自分で何かサービスを出したいという方は多いかと思う。今回はそんな方へ最低限知らなければならないリストを上げようと思う。ターゲットとしては Web アプリケーションということにしたい。

UNIX コマンド

最初は黒い画面に慣れる必要がある。いつまでも Mac の Finder でダブルクリックしてるようではプログラミングの効率が悪すぎる。UNIX に関してひとまず知らなきゃいけないのはディレクトリ/ファイル操作閲覧やエディタ(Vim or Emacs)、各種プログラミングコードの実行といった基本的なことで十分だ。次第にリダイレクトやパイプとかを知っていくと、より効率的な操作ができるようになる。最初から一気にマスターする必要はないが、シェルスクリプトとかも書けるとさらに良い。興味の度合いに応じて UNIX を学んでみよう。

これらはとても基本となる操作であり、UNIXの基礎を知らないと、これから学ぶことに対してことごとく UNIX コマンドから調べなきゃいけなくなったりと地味にきつく挫折する原因にもなりうるので最初にがっつりやってみよう。

例えば以下のような本。読んでないけどおそらく正しいこと書いてると思う。

MacOS XユーザのためのUNIX入門―ターミナルから覗くUNIXの世界

Ruby

ひとまず Web アプリケーションなら Ruby でいいだろう。なぜならあらゆるドキュメントが整備されていて、いろいろな問題にあたってもネットにたくさん情報があり、そして何より書いていて楽しい言語だからだ。複雑でぐちゃぐちゃになるような言語(何とは言わないが)を使うと、プログラミング自体がつまらないものになってしまう。考えてみてほしい。これからあなたはプログラミングをすることになるが、そのコードと四六時中付き合わないといけない。 楽しく学べる Ruby がいいと私は思う。(ここら辺はいろいろと論争を生むところだからあまり突っ込みはしないでいただければ幸いだ)

Ruby でターミナル上で動く簡単なサンプルプログラムを書けるようになろう。ruby test.rb とかを実行して色々と学んでいくのだ。Ruby と UNIX は当然のことながら深く結びついているので、UNIX を深く知れば知るほど、Ruby とのつながりを感じて感動することもある。

これに関しては 2冊くらい読んでおいたほうがいいと思う。王道がこの2冊。

たのしいRuby 第5版

プログラミングRuby 1.9 −言語編−

後者は Ruby 1.9 とちょっと古いんだけど、Ruby 2.x でも十分動くと思う。ちょっと古くてもお勧めしたい本だ。

HTTP

HTTP プロトコルはあらかじめ知っておいてたほうがいい。これを勉強しないでいると、今後の Rails の勉強の時に意味わからないことがたくさん出てくる。本当に基本だけでいいので、さらっとだけでも本を読んでおくといいだろう。

特に GET/POST などの HTTP メソッド、200, 400 などの レスポンスコード、Cookie、セッション などは知っておいたほうがいい。これはWeb標準なので今後絶対に知らないといけない知識になってくる。

HTTPの教科書

HTML/CSS/JavaScript

Web ならこの基本を押さえておかないといけない。この3つに関してはいろいろな本が出回っているから、自分にあったのを読めばいいと思う。最近は HTML5 とか CSS3とかもでてきて情報が錯乱しつつあるので、ググりながら実力をつけるってのがちょっと難しくなってきてる感じもする。

こういうのは必要な時に必要なコードが書ければいいと思うので、辞典っぽいのを買って一通りさらっと読んで気になるのがあればコード書いてみてブラウザで確認するみたいなことをすればいいんじゃないかな。

例えば好きなサイトの完全コピーを HTML/CSS/JavaScript で作ってみよう。そこで「これどうやってやるんだろう?」ってのが出てくることかと思う。そんな時は Chrome Console を開いて、HTML要素やCSSを見て理解できるようになろう。

詳解HTML&CSS&JavaScript辞典 第6版

Web開発でよく使う、特に使えるChromeデベロッパー・ツールの機能 - Build Insider

jQuery, jQuery プラグイン

今でも大活躍の jQuery。初学者は jQuery を知ることは今でも有効だと思う。 DOM 操作によってページの要素が動的に切りけるような基本を身につけることが重要だ。最初は汚いコードでも構わないので、jQuery で色々と遊べるようになるとサービス作成の幅が広がると思う。また、それにあわせて ajax も早いうちに学んでおくと、なお良い。

jQuery プラグインでさらに自分の欲しい機能を早く実現できるような仕組みも学んでみよう。DOM操作ができれば、そのjQueryプラグインをさらに自分好みにカスタマイズできるようにもなるだろう。大事なのはとにかく自分で書いて JavaScript を好きになること。それこそがさらなる勉強の意欲と成長を生むからね。

jQuery レッスンブック jQuery2.X/1.X対応

データベース

Web アプリケーションを作るなら、データベースの知識は必須だ。今でも現役バリバリのリレーショナルデータベースを理解しよう。テーブル設計を正しく行い、SQL が発行できるようにならないといけない。

これも勉強してみればパズルみたいなもので案外面白いものだ。ビビらずに軽い気持ちでチャレンジしてみてほしい。

【改訂第3版】 SQLポケットリファレンス (POCKET REFERENCE)

まずは最低限の SQL さえかければいいんじゃないかな。今後ゼロからがっつり Web アプリケーションを作るならテーブル設計も正しくできるようにならないといけない。

Git, Github

Git はソースコードを管理するためのバージョン管理システムだ。あなたが書いたコードを前の状態に戻したかったり、他のメンバーと開発したコードを組み合わせたり、そんな作業を Git はしてくれる。これも絶対に学んでおかないといけない技術になってきている。

最初のうちはそこまで詳しく知る必要はない。add, commit, branch, checkout, push, fetch, merge, log, diff くらいで最初は十分だろう。

Gitが、おもしろいほどわかる基本の使い方33

この時点で自分の Github アカウントも作っておこう。

Ruby on Rails

ついにだ。やっとここで Ruby on Rails を学習できるようになる。ここまでの基礎がないと、Rails を学んでも自分の作りたいアプリは作ることはできない。決してここまでの勉強は無駄ではないので安心してほしい。

Ruby on Rails は今までの総まとめみたいなものだ。今まで学んだ知識をうまく組み合わせてくれるのが Ruby on Rails だと思ってもいいかもしれない。ここでも何冊か本を読んでしっかりとマスターしたいところだ。

RailsによるアジャイルWebアプリケーション開発 第4版

パーフェクト Ruby on Rails

Heroku

作ったアプリを公開するときにはサーバーが必要だ。 Heroku。この神がかったサービスをぜひ使おう。あなたの書いた Ruby on Rails コードが数行のコマンドを叩くだけで世界中に公開できる。こんな素晴らしいことが他にあろうか。

ここまでくると Qiita とかでたくさん記事が出回っているので、それらを読んでデプロイしてみよう。なぁに、ここまで勉強してきたあなたなら難しいことは何もない。一番簡単な記事はこれかな。

railsアプリを5分でherokuにデプロイする - Qiita

独自ドメインとか SSL とかそういうのもみんなネット上に情報はたくさんある。問題なくできるはずだ。

終わりに

ここまで学べば、ある程度自分の力で Web アプリケーションが作れるようになるだろう。ここから先の技術は、自分でどんどん作って壁にぶち当たり、その壁を突破していくことで体得し、成長することができる。

そのぶち当たった壁はあなたのブログに書き残していってほしい。あなたの貴重な時間の記録を残すという意味で重要だ。その情報が次なるプログラマーを助けるヒントになるだろう。

本気で Web アプリケーションを作りたいあなたなら、きっとここまで勉強してくれることだろう。ぜひこのレベルにまで来てほしい。そしていつかたくさんの人に使われる Web アプリケーションをあなたの手で作り上げていただきたい。その日が来るのを私は心待ちにしている。

Heroku on Rails アプリのメモリ増加対策の方法

ども、@kimihom です。

今うちが運用しているサービスの Heroku メトリクスを眺めていたら、いつの間にかメモリが90%近くまで届く瞬間が来てしまって、いよいよこれは R14(Out of Memory) が発生してしまいそうな感じが出てきたのでいろいろ対策を練った。

詳しい方法は Heroku 公式の英語ドキュメントに書いてあるが、そのうち効果的と思われる幾つかのことを実践したのでその結果とともにまとめようと思う。

Derailed Benchmarks Gem の導入

Derailed Benchmarks は Rails 及びその他 Ruby アプリの各種ベンチマークを取ることのできる Gem だ。

この中で、最も手軽に実践できるのが、 bundle exec derailed bundle:mem コマンド。 これは、 Gemfile で使っている Gem のうち、どの Gem がメモリを食っているのかを調べることのできるツールである。これで、例えば明らかにメモリを食い過ぎている Gem があれば、その代替を探して置き換えたりすることで Rails アプリ起動時のメモリを抑えることができる。

私はこれで 80 MiB くらいだったのを 60 MiB くらいに下げることに成功した。明らかに無駄にメモリを消費している Gem を見つけられたのが幸運だった。これにより、Heroku Dyno 再起動直後のメモリ使用量をだいぶ抑えることに成功した。

とはいえ、Heroku の1日1回行われる再起動の時にメモリがガクッと落ちて、しばらくするとまたどんどん上がっていってしまう問題は継続中だった。

そこで Derailed には、その他に各アクションごとに定期的にリクエストを走らせてメモリリークが起きていないかをチェックできるツールなども用意されている。ただこれは URL, HTTP メソッド ごとに設定を変えて何度もやらないといけないし、見つけるのが結構困難だったので、私の場合はうまくいかなかった。

Scout の導入

Scout は Rails アプリ専用のモニタリングツールだ。この分野では NewRelic がダントツで有名かとは思うが、あの Gem 自体も結構メモリを食うし、何より最近重いとの評判だ。そんな中、 Scout は Rails のモニタリングツールの新星として登場してきた。

Scout のいいところは、 N+1 クエリを勝手に集計して管理画面で対象アクションを表示してくれたり、メモリーブロートの起きたアクションを表示してくれたりするという点。 それ以外のメトリクスってぶっちゃけ Heroku 標準の メトリクスで十分だよねってのがある。

ここで、メモリリークとメモリブロートの違いについてちょっとだけ説明する。詳しくは Scout のドキュメントに書いてある。メモリリークはリクエストがどんどん来て、ちょっとずつ徐々にメモリが増加していってしまう問題。Ruby の GC がうまく働かないようなソースを書くと、これがどんどん増えていってしまう。リクエストが増えれば増えるほど、その増加率は高くなって、しまいには Out of Memory (R14 エラー) となって極端に Rails アプリが遅くなる現象が起きる。対してメモリブロートはある特定のユーザーがスロークエリを投げてサーバー内のメモリが一気に増加する現象だ。ここで、両者について Scout のドキュメントでは以下のような記述がある。

If your app is suffering from high memory usage, it’s best to investigate memory bloat first given it’s an easier problem to solve than a leak.

Rails アプリが高メモリの問題を抱えているなら、まずはメモリブロートを調べるのが最善の策である。それはメモリリークよりも解決するのが簡単である。

ってことで、 Scout アドオンを導入すると、メモリブロートのリクエストが何だかってのが一発で表示される。

今回の例では、人のアイコンが一人だけなので、1つのリクエストで一気にメモリブロートが発生したことがわかる。それぞれどこでメモリを食っているのかがわかるので、何かしら対策ができるとのこと。

ここで私が今悩んでいるのが、対象のアクションはわかったものの、具体的にどう直せばいいのかが全くわからないという点だ(致命的)。よく見てみると、どうやらDynoの再起動直後のリクエストがほぼ間違いなくメモリブロートが起きているようだが、これを対策することなんてできるのだろうか・・。一応 Scout のドキュメントにあるのが ActiveRecord の select を用いて text や binary のカラムを無駄に取ってこないようにする、N+1 クエリーを除去する、無駄にたくさんのオブジェクトをレンダリングしない、重いファイルアップロードを Rails を通して行わない、といったものだ。ひとまず ちょっとした N+1 クエリを Scout で見つけることができたので、そこでどれくらい改善できるかを見ようと思っている。

N+1 クエリも今までは 適当に includes を使って対応してたけど、eager_loadpreload, joins といったのをちゃんと使い分けた方がいいことを学んだ。ここら辺ちゃんと学んでおいた方がいいだろう。

それでも解決できないなら・・

それでも解決できず、メモリ使用量が100%超えを連発してしまっているなら、 Dyno アップグレードの時が来たということなのかもしれない。どれ選べばいいのっていうのも Heroku の記事として上がってるので、これをちゃんと読むようにしよう。

ほとんどは standard-1x dyno を増やしていけばいいように思うが、どうなんだろうか。ここら辺の知見がとても欲しい!

終わりに

まだまだメモリ使用量が落ち着いている状況ではないため、引き続き調査・実験・検証していく次第だ。

幸いにも最後の手段として Standard-2x に上げたり、 Standard-1x を3,4個くらい増やすくらいの金銭的余裕はあるので、ここら辺も実践してみてどれくらい改善したのかが分かり次第レポートできればと思っている。

本格的に Heroku で Web サービスを運営するなら、パフォーマンス問題は必ず通る道だと思うので、まずは私が突っ走っていきたいと思っている次第である。

Startup Rails で知っておいた方がいいかもしれない6つのこと

ども、@kimihom です。掲題のタイトルで以下のミートアップで発表した。

第一回スタートアップRails勉強会 - connpass

発表資料はこれ。

Startup Rails ってテーマなので、てっきり 0を1にする人たち向けかな、と思ったらそういう視点での発表は2つしかなく、他は1を10 や 100 にするフェーズの方々の発表が多かった。

補足的な

私たちは実際大きなピボットと小さなピボットのそれぞれを実施し、市場のニーズによって事業を柔軟に変えてきた。ようやく最近は Product/Market Fit を見つけられた段階まで持ってこれたので、製品の品質の改善に力を注いでいる状況になれている。うちのサービスは品質を意識してやってるよってのが今回のブログで一番伝えないといけない補足である。

0を1にするフェーズのエンジニアに求められるものってのは、普通のエンジニアとは訳が違う。よく言われているエンジニアの常識的なものは通用せず、ただひたすらにサービスをぶっ壊しては作り直して検証することが求められるのだ。だからこそ必要な知識やスキルがあるのだ。その点を発表を通じて伝えたかった。

Startup エンジニアの本当に難しいところ

toB のビジネスなら Product/Market Fit まで持っていければ、マネタイズもうまくいくことだろう。そこまで行くには当然ながら辛い道が待っているけどもね。

toC の場合はもっと辛い。toC サービスの成功レベルで言えば10万、100万ユーザーが基本で、それでようやく"土台ができた"と言える段階だ。そしてその後にさらにマネタイズどうするのってところを考えないといけない。そのサーバーの負荷を支えるのにまたエンジニアが必要になるだろうし出費も増える。そんな中でユーザーから出費と給料をまかなえるようなマネタイズをしていかないといけない。普通に考えてそれがうまくいくはずがない。いきなり広告が沢山出てきてうんざりした toC サービスを読者の方なら複数個思い浮かぶことだろう。だからこそ toC は夢がある分、過酷な道が待っているのだ。

次回以降の Startup Rails はそういう辛い時期や判断が必要な時の Rails アプリ開発はどうしてきた的な話をぜひ聞きたいなと思う。Startup として辛い時に、いかにして Rails を使って高速に機能を実装し、あらゆる外部サービスを駆使して効率化を図ってきたか。そのストーリーを私は聞きたいと思っている。現在進行形でそのフェーズにいるエンジニアってのは忙しすぎてそんなミートアップに参加してる暇すらないのかもしれないので、 経験者がどんどん語る場にしていけたらいいんじゃないかなぁ。

確かに私の理想とする Startup Rails の話をできる母数は圧倒的に下がるだろう。スタートアップで成功した CTO レベルの人たちじゃないとこの時期の話はできない。でもだからこそそういう経験をどんどんと次の若い世代に伝えていってほしいし、それが新しくサービスを立ち上げようとする若者の勇気を与えるのではないかな、と思う。

私は本気で起業して 0から1を作ろうとする若手スタートアップエンジニアにエールを送ることのできるエンジニアになりたい。

終わりに

懇親会では同じような創業メンバーとしてエンジニアに入った数人の方と交流することができた。まさに私が聞いて欲しいと思ったフェーズを経験した方に共感してくれて、それはそれは嬉しかった。

また Startup Rails は開催されるらしいので、参加できれば参加したいと思う。懇親会も長めにとってくれて早めに終わるし、健全でいい場だと思うので運営さん今後とも宜しくお願いします。

Rails の render で部分的に動的な HTML を生成する

ども、@kimihom です。

Rails で CSS フレームワークとかを使っていると、例えばモーダルウィンドウを出すためにヘッダやフッタで共通の HTML を使うことになるだろう。これらは大抵の場合、共通の UI となる。それでも当然、モーダル内の body の部分はそれぞれ別々の HTML を書けるようにしたい。そんな場合にどうしたらいいのかをご紹介しよう。

共通部分を 別 html で切り出そう

Rails といえば DRY(Don't Repeat Yourself)だ。同じコードをコピペするようなことはしてはならない。それは HTML でも同様のことだ。同じコードが出てくるようなら、まずは app/views/home/_modal.html.erbのように切り出そう。今回のHTML断片は Bulma を使ったモーダルの例。

modal.html.erb

<div class="modal <%= class_name %>">
  <div class="modal-background"></div>
  <div class="modal-card">
    <header class="modal-card-head">
      <p class="modal-card-title"><%= title %></p>
      <button class="delete"></button>
    </header>
    <section class="modal-card-body">
      <%= yield %>
    </section>
    <footer class="modal-card-foot">
      <a class="button is-primary action"><%= action_name %></a>
    </footer>
  </div>
</div>

そんで、呼び出し元の HTML を <%= render %> の引数とブロックで値とHTMLを引数として渡すことができる。

<%= render layout: "modal", locals: {
  class_name: "hello",
  title: "Hello World",
  action_name: "Agree"
} do %>
  <p> Are you agree? </p>
<% end %>

こうすれば、柔軟なモーダルがどんどんと量産することが可能だ。注意が必要なのは、renderlayout オプションで指定してあげること。こうしないとブロックを利用することができなかった。

あとは JavaScript 側で Modal を表示するような処理を書けばOKだ。

モーダル内容を JavaScript で動的に書き換える

まぁたいていの場合ってのはこのモーダル内容をさらに JavaScript で動的に表示したいということがあるだろう。 Rails の View 内でそれが完結できればいいが、 JavaScript 側の値で動的に表示したい場合は、modal 表示前のイベントをキャッチして、HTMLを書き換える必要がある。

  $(document).on("click", "#console-ctrl .open-modal", function() {
    var target = $(this).attr("data-modal");
    var attr = $(this).attr("data-modal-attribute");
    $target = $("#console-ctrl .modal." + target);
    $target.trigger("modal:before-open", attr);
    $target.addClass("is-active");
  });
  
  $(document).on("click", "#console-ctrl .modal .delete", function() {
    $("#console-ctrl .modal").removeClass("is-active");
  });

  $(document).on("modal:before-open", ".modal.hello", function(attr) {
     console.log("hello modal before open");
  });

こんな感じにしてあげれば、 モーダルを表示する HTML 側で共通で書くことができる。

<i class="fa fa-plus-circle add-person open-modal" data-modal="hello"></i>

このフォントをクリックすると、さっきの hello なモーダルが表示されるようになる。そしてその描画前に、modal:before-openのイベントが発火するようになる。

終わりに

特にCSSフレームワークとかを使っていると、共通な部分ってのはよく出てくる。これらをうまく共通化して、テンプレートとして保存するようにすればより美しく汎用性の高いコードを書くことが可能だ。

今回は jQuery の trigger を利用した。この trigger については以下の記事でご紹介しているので、もし知らなかった場合は調べておくと良いだろう。

今更ながら jQuery の trigger の魅力について語らせてもらう

Increments ++ Tech Talk に参加してきた

ども、@kimihom です。

今日は今をときめく Tech 系スタートアップ Qiita さんにて開催されたIncrements ++ Tech Talkに参加した。個人的に最近 Rals 5 でアプリを作り始めていたのでちょうどいいタイミングでちょうどいいテーマだった。

connpass.com

個人メモなのでかなり端折ってるけどメモ内容を上げておく。

# Rails5
## WebSocket と ActionCable

シームレスなRailsインテグレーション
Rails::Engine をマウントする実装なのでWebSocketサーバーを切り離せる
Unicorn と EventMachine が相性が悪い
スケールを考えるとPuma必須

Rails 側で Channel を作成してJS側で購読
- bloadcast で Channel購読者に配信
- bloadcast_to で個別配信


高頻度イベントにまつわる状態は Redis が向いている
リアルタイムデータを Redis で保存して、永続化(ログアウトしたらとか)にデータベースに保存

## Rails 5 アップデート
attr_protected が使えなくなる
submit_tag の disable_with がデフォルトになる

active_record.warn_on_records_fetched_greater_than
たくさんのクエリ結果を返す時に警告を出す

accessed_fields メソッド
どの属性にアクセスしているかを調べられる
select で限定すればちょっとはやくなる


Drop jQuery as a dependency!!
> これヤベェw

ActiveJob の再実行がよりスマートになった

ActionCable は趣味アプリでどんどん使っていくには面白く使えそうだ。たくさんリクエストを裁くことを考え始めるとまだどうなることやら、といったところ。自分がリアルタイム系のを作るんだったら Firebase か Twilio Sync を使うだろうなぁ。餅は餅屋ってやつ?何でもかんでも Rails でやらせるってのは判断に迷うところである。

Rails 5のアップデートに関しては、自分の本業の Rails アプリは 4.1 から作り始めたプロダクトだからあまりアップグレードは大変ではなさそう。それよりも関連Gem のアップデートの方がまだ安全にアップグレードするには時間がかかりそうな感じである。てことでわざわざ荒削りな レールを渡る必要はまだ特にないかなー。

Rails 5.1 で jQuery なくそうぜ 的な話が上がってるのが個人的には割と困るw 自分のコードだけ無くせばいいって話ではなくて jQuery プラグインもどうするかってのを考え出すと、こりゃあ困ったといったところである。 ただ新しい JavaScript は jQuery っぽい書き方が簡単にできて、もはやブラウザ間の誤差も気にならなくなってきたからという背景があるようなので、それらのライブラリも次第に jQuery に依存しない シンプルな JavaScript ライブラリになることだろう。てことできっと時間が解決してくれるだろう、といったところ。

今は ActiveJob とかのバックグランドタスクは全部 AWS Lambda に投げとばしてるんだけど、 DB絡めるところとかが Node.js で SQL 叩くよりかは ActiveRecord で扱えた方が楽だなぁと思うときはある。てことで ActiveJob の利用はそのうち(いつになるかは不明)検討しようと思っている。

俺と David

今日は DHH に思いを巡らせる日にもなった。この写真を拾い出してきた。ちなみに DHH の左が私ねw この笑顔よ。そりゃ嬉しいよね!

f:id:cevid_cpp:20160819000918j:plain

んで懇親会を話している中で、 Rails が好きなだけでなく、 Bascamp の運営や思想そのものに共感している方々がいることに感銘を受けた。 Rails は スモールチームが適切なシステムを作れるようになるために存在するのである。

このスレッドはかなり面白くて micro serivce についての DHH の考えも言及されてある。

こんな そもそもの "Why Rails" のお話や、「小さなチーム大きな仕事」って本を何回も読んで勉強して Rails でスモールチームで 革新的な Webサービスを作ろうとしている方だったり素晴らしい同志とも言える方に会うことができて嬉しかった。

あとは 各地で開催されている ~~.rb 系の勉強会にも機会があれば参加してみようと思った。割とああいうのって初見が1人で行くのは気が進まなかったけど、やっぱり一人で rails とかで悩むよりかは、それを共有してみんなで解決していく。他の誰かが悩んでいた時は私も考えることができるし. そういったことがコミュニティのより良い関係を築くことができるのだろう。

イベントレポートまでが勉強会ってことで、今回はそんな感じの素晴らしい勉強会でした。

Rails5 でフロントエンドを綺麗に扱う方法を考えてみた

ども、@kimihom です。

SMAP解散騒動が騒がれる中、新規プロジェクトとして Rails 5 のプロジェクトで色々と遊んでみている。その中でフロントエンドの部分の書き方で自分なりに答えを出しながらやっているので、そこの方法をシェアしようと思う。

JavaScript の書き方

まず、最近よくあるフロントエンドのツール(BrowserifyやWebpack, grunt や gulpなど)は使わない想定。あくまで Rails の提供する範囲内で 最大限 JavaScript を美しく保つ方法を記す。

最初はapplication.html.erb のレイアウトから。

<head>
  <title>My App</title>
  <%= csrf_meta_tags %>
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>

  <!-- CDN -->
  <script src="//....js"></script>
  <!-- app -->
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

</head>

CDN から読み込む系の JavaScript は、jQuery に依存しない JavaScript コードだけを読み込むようにするのが注意。jQuery に依存する場合はapp/assets/javascripts/vendorディレクトリに突っ込む必要がある。jQuery の読み込みは application.js の方でやるため、順番が後になってしまうからである。それさえ気をつければ CDN は1行で読み込みが完了して楽なので積極的に利用していいと思う。

この方法はシンプルが故の欠点があって、JS ライブラリの依存関係とかそういうのを考えないような設計になる。そのため、今後のアップデートで他のライブラリが動かなくなるんじゃないかとかそういう心配をする方にはお勧めできないのかもしれない。ただ、手軽さで言えば断トツでこの方法だろう。

さて、続いて application.js へ移ろう。これは割とシンプルで Rails 搭載の JSライブラリ、外から持ってきたJSライブラリ、自分のJavaScript ファイルの順番で読み込む感じになる。

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_directory ./vendor
//= require_directory ./main

続いて個々の JavaScript の書き方。だいたいのイメージがつかめるように、特に意味のないコードを含めている。

let ConsoleCtrl = (function(){
  var localVariable;
  
  function privateFunc() {
    localVariable = "local";
  }

  $(document).on("click", "#console .btn", function() {
    localVariable = "clicked";
  })  

  return {
    publicFunc: function() {
      return localVariable;
    }
  };
}());

いくつか大事な点がある。まず一つ目に(function() {...}()) でくくることで、JavaScript スコープをこのファイル内にとどめるようにしている。結局 Rails は作ったファイルを一つに統合するので、何も考えないでコードを書くと JavaScript のグローバル領域を汚染することになるのだ。function でくくることで、グローバルになるのは、ConsoleCtrl だけになる。そんでlocalVariableを外のJavaScript ファイルから読み込みたい場合は、return で関数を含んだオブジェクトを返すことで対応できる。こうすれば ConsoleCtrl.publicFunc() でメソッドを呼び出すことが可能だ。

そして、 jQuery の書き方は基本的にすべて$(document).on(~~) の書き方になる。これは HTML が常に動的に書き換わるため、ロード完了後のHTMLだけのイベントしか定義できない $("#elem").click(~) の書き方は正しく動作しないためだ。一見動作が遅くなるように見えるけども、何十個もこの書き方をしても、ほとんど速度に関して違和感を感じることはない。

あと最後に、ページを初期化した時に呼びたい JavaScript があった場合にどうするかって話なんだけども、これは jQuery の trigger を使うことで対応している。 Turbolinks にも各種イベントがあるんだけども、全部の JS ファイルに依存するイベントになるので採用しなかった。では実際にどうするのかっていうと、HTMLに triggerを記述する。こんな感じ

<!--  HTML  -->

<script>
  $("#main-ctrl").trigger("main:loaded")
</script>

んで JavaScript 側に通常と同じようにイベントを定義してあげる。

$(document).on("main:loaded", "#main-ctrl", function() {...})

"初期化イベント"っていうくくりで初期化ができるので、割と直感的になっていると思う。

CSSの書き方

これは別に rails 5 に限った話じゃないんだけども、普通に application.css.scss 通りに書くと、変数の読み込みがうまくいかなかったり、Sass をうまく使いこなせていない感がある。てことで、ちゃんと Sass を使う方法として以下のようにしている。

まず application.cssapplication.css.scssに書き換える。そんで以下のようにすべて importでファイルを読み込んでいる。

@import "bulma/bulma.sass";
@import "partials/*";

今回は CSS フレームワークの bulma を使った例。bulma は Sass ファイルのテンプレートを用意してくれてるので、そこに用意されている変数も app/assets/stylesheets/partials ディレクトリ内のすべてのファイルで読み込むことが可能だ。

JavaScript も Stylesheet も、開発時にはキャッシュが効いてしまって色々と面倒なことになりがちなので必ず開発者ツールを起動してキャッシュがかからなくするようにすること。

終わりに

いつまでも Rails のフロントエンドの議論は尽きない。方法は人それぞれだと思うので参考程度にしてみていただけたらと思う。自分のアプリの場合、Gmail のような1ページで収まるシングルページなので、Turbolinks の恩恵はあまり受けないかもしれない。引き続き Rails 5 を触ってみて、Turbolinks 5 や ActionCable などで有用な情報が見つかればシェアしていきたいと思う。

Rails5 が示したサービス開発の新しい指針についての考察。

ども、@kimihom です。

f:id:cevid_cpp:20160702014256p:plain

Rails5.0 の正式版がついにリリースされた。

Riding Rails: Rails 5.0: Action Cable, API mode, and so much more

Rails 5といえば、 ActionCable での WebSocket によるサーバープッシュのリアルタイム処理が注目されがちだが、個人的には今後のシステムの開発指針を Rails が示した重要なリリースになっていると感じている。その原動力となっているのが、 あの "Turbolinks" だ。

マルチプラットフォーム開発に対する提案

ではどんな話かっていうと、まず Rails としては JavaScript で複雑なロジックをたくさん書いたり状態を管理するような処理を書かないことを選んでいる。以下の動画は今後の Rails において非常に重要な意味を持っている。

RailsConf 2016 - Turbolinks 5: I Can’t Believe It’s Not Native! by Sam Stephenson - YouTube

ではどうするのかっていうと、 Turbolinks によるページの書き換えだ。処理は全て Ajax を通じてサーバーサイドのHTMLレンダリングを通して中身を JavaScript で書き換える。そうすれば状態管理をしなければならないのは相変わらず Rails の DB 側になり、フロントエンド側のロジックが一気に減ることになる。

これだとスマホアプリが作れない? それが最新の Turbolinks のすごいところで、 iOS, Android 用になんと Turbolinks がネイティブと WebView を組み合わせてスマホアプリとスマホWebの垣根を限りなく少なくしてくれたのだ。そうすると各ネイティブアプリで書かなければならないロジックは本当に少なくなって、最も重要な部分は Web で統一化されているのである。私たちが Web の開発によりフォーカスを当てることができる。

この考えは確かに割と前からあった。ただし、 ネイティブの WebView があまりにも残念だったため、やっぱネイティブのJavaやSwiftで書かないとダメだよねーってのが共通認識だった。しかしながら スマホとHTML5 の発展により、そうした問題が解消しつつある。満を持してついに Rails が Turbolinks と WebView ベースを組み合わせたアプリの開発手法を提案してくれたのだ!

レスポンシブ対応な Webアプリケーションを作れば、 PC Web, Tablet Web/App, SP Web/App の5つに対応したものが高速で開発できる。これが次の世代の Rails のレールなのである。

Rails API で他の道も示している

このような開発手法だと、 Webアプリベースのサービスを アプリ化するにはちょうどいいのだけど、ネイティブビルドに大きく依存するようなサービスを開発する上では Turbolinks だけでやるのは不可能なことである。その場合は Rails API を使って JSON ベースでやりとりするような設計になるだろう。作りたいサービスが Turbolinks にマッチしなければ Rails API もあるよって意味合いで Rails API を公開している感が強い。

もちろん React や Angular 好きのためにってのもあるんだろうけど、それは付随的なものであって Basecamp 的主張で言えば、React や Angular を Rails で使うのはあまりイケてない感がある。なぜなら上記プレゼンの中にも「We are not Google. We are not Facebook」 ってある。これはそんな大規模なアプリを作れるようにするために Rails が存在するのではなく、小規模のスタートアップがより早く優れたものを作れるようにするためのフレームワークであるからって意味でとても納得できる。 ま、それらを使っても Rails のレールから外れるっただけなので、苦労してでもやりたきゃやればって感じなのだろう。

Rails 5 へのアップデートは。

こうやって正式リリースが出ると早くアップデートしたくなるものではあるが、Rails 4を本番で稼働している場合はまだやるべきではないと思う。依存 Gem の問題もあるし、まだ出たばかりなので激しい頻度でアップデートが繰り返されていくことだろう。そこまでしてアップデートした先にあるメリットって自慢できるくらい? あとは ActionCable とか 新しい Turbolinks を使わないといけないみたいな場面だったらアリかもくらいか。

この辺は個人の好みなのでやりたければどうぞと言ったところである。

私はそんなことよりも新規プロジェクトを Rails 5 で作り、 Turbolinks の新しい設計思想に触れてみたいと思っている。これは誰にとってもバージョンアップ作業をするよりも大事なことであろう。

今回の Rails 5 の登場がサービス開発手法の新しいスタンダードになることを期待している。

Rails を学んだ後に学びたいオススメ技術

ども、@kimihom です。

たまには Rails 初心者向けのコンテンツでも書こうと思い立った。 Rails を本なりなんなりで勉強した後、どういった技術を学ぶべきなのか。私のオススメする順番でご紹介していこう。

対象者

主にWeb アプリを作りたいと思っている Rails エンジニア。今回は スマホアプリとか フロントエンドの話はしないことにする。Bundler を扱えて、Rails の AssetPipeline, ActiveRecord 周りはそれなりに理解したけど、そのあとどうするのっていうくらいな方。

Heroku

Rails ならこれというくらいの定番。 最近では Rails の本にでも Heroku が登場することが多くなってきた。 Heroku を使えば、ローカルで開発した Rails アプリを公開して運用することができる。せっかく Rails でアプリ作れるようになったら、そのグレートなサービスをみんなに見てもらいたいところ。Heroku を使えば 5分もかからずに公開することができてしまう。 Heroku は Rubyist を Hero にしてくれるのだ。

メールをどうする? ログやアラートの管理は?HTTPS にするには? そういった Web の共通の課題は全て Heroku アドオンが解決してくれる。私たちはポチッと使うアドオンをクリックするだけで便利な機能を利用することが可能だ。 Chef? Ansible? Capistrano? そんなこと全く知らなくて OK。そんな所にコードを書く時間があったら、サービスの改善に時間を使おう。Heroku と その周辺のアドオンがインフラのあらゆる悩みを解決してくれるのだ。

Heroku はアメリカにサーバーがあるからレイテンシが〜。そんな声は無視しよう。実際に使えばわかるが、Heroku を使って遅いと感じることはほとんどない。Rails 初学者に必要なのは、自分たちの作りたいサービスがどんどん出来ていくその過程と、その実現のしやすさだ。それを実感していく中でどうやったら Heroku x Rails で速くするかは自ずと学んでいくことだろう。

AWS の一部

AWS は最近どんどん新しいサービスを出してきているが、Heroku を使っていれば知らなければならないことはそんなに多くない。私がオススメする以下の AWS を最低限マスターしておくと良いだろう。

  • S3。画像などのファイルのアップロードや閲覧などの静的ファイルを置く場所として有用。
  • Route 53。ドメイン周りの管理をしてくれる。独自ドメインを運用していきたい時に有用。
  • Lambda。 Rails の一部のコードを外に切り出してレスポンスを早めたり、定期的に処理をさせたい時に有用。
  • Cognito。 Web や スマホアプリからAWSサービスにアクセスする際に有用。
  • IAM。 AWS の権限周りの管理。

このくらいだ。他は類似した Heroku のアドオンを使ったほうが手っ取り早いし安上がりに済む場合が多い。他の AWS サービスは概要を知っておくっくらいで、後に回して良いだろう。

Redis

Redis を"キャッシュストアだ"と思うだけでは Redis の本当の素晴らしさを分かっていない。Redis は非常に柔軟な KVS でいてとても高速だ。Redis は PostgreSQL などの RDB では実現が難しいような痒い所に手が届く素晴らしい技術である。

例えば、一時的にデータを持っておきたいんだけど一定時間後に削除していいようなデータがあったとしよう。RDBでは定期的に削除するバッチ処理などを実装しなければならないが、Redis であればタイムアウトを設定することで勝手に消えてくれる。Key に自由な値を設けることで、RDB さながらの実装を Redis だけで実現できてしまう。この詳細については Redis の本を学ぶとイメージがつきやすいだろう。

Redis入門 インメモリKVSによる高速データ管理 : Josiah L. Carlson, 長尾高弘 : 本 : Amazon.co.jp

Heroku Redis として標準のアドオンとして提供されているので、 KVS であれば Redis という選択は賢い選択と言えるだろう。

Elasticsearch

たいていのサービスでは"検索"機能を実現したいということになるだろう。 Heroku Postgres では日本語の全文検索をサポートしていないので、 Elasitcsearch を使う決断をすることにいずれなる。Rails と Elasitcsearch を簡単に扱えるような Gem があるので、概要をさらっとドキュメントを読んで Sense を使いながらデータの出し入れと検索ができるようになればひとまずは OK 。日本語のドキュメントが全然なくて最初は苦戦するかもしれないが、Elasticsearch に限って言えば実際にインストールして使ってみながら改善していくスタイルでいいと思う。 Elasticsearch 周りの話はこのブログでもたまに取り扱ってるので気になる方はタグの Elasticsearch からざっと眺めてもらえれば幸いだ。

Elasticsearch 自体は Heroku のアドオンとして豊富に取り扱っているので好きに選べば良い。AWS でもいいけど。

終わりに

一気に書いていったが、まず一番大事なのは基本であると改めて書いておきたい。Rails より HTML/CSS/JavaScript のフロントエンド。フロントエンドよりも HTTP やCookie、セッションなどの基本的な概念だ。というのも Web の性質 をしっかりと理解しないと Rails コードにおいて簡単にレールを踏み外して、最高にカオスなコードを書き散らかす初学者が後を絶たないからだ。Rails を学んだらもう一度 HTTPの基本から始まり、 Rails の ActiveRecord, ActionView, ActionController などをしっかりと理解しておきたいところ。テストコードが自然に書けるようになれれば、 Rails エンジニアと名乗ることができよう。

今回紹介した技術はその基礎があって初めて応用できる分野とも言える。基礎を吹っ飛ばしていきなりこういう技術に手を出すのもいいけど、結局 Rails の基礎が足りないといつか気づいて後戻りするだけだから、ルートとしてはどちらでもいいのかもしれない。

エンジニアを成長させる一番の材料は「好奇心」だ。あの技術はどれを使ったら実現できるのだろう?というアンテナを常にめぐらせ、それに飛び込む。そうした思いっ切りの良さこそがいいエンジニアになるための条件である。是非とも好奇心のあるエンジニアの仲間になって世界を変えるサービスを作って欲しい。同じ思いを持つ私からの僅かながらのメッセージである。