Rails5 で WebSocket を ActionCable でなく Firebase でやった話

Ruby on Rails Advent Calendar 12日目です!

私は仕事では iOS を Swift を書いていて、個人開発でサーバサイド APIRails で書いています。

そこで WebSocket を使いたいと思い ActionCable でやろうとしてたのですが、 Firebase でもいけるんじゃねと思いやってみたらかなり良かったため、その話をします。

ただ書いている途中で知ったのですが、悲しいですが現状この方法は Firebase から推奨されておらず後で使えなくなる可能性がありますので、利用しない方が良さそうです。。。 😢

f:id:star__hoshi:20161211184034p:plain

要件: タイムラインを形成したい

Twitter を想像してもらえれば良いです。
ユーザが何かを投稿して、それをみんなで見る、そのタイムラインを形成したいという要件でした。

ただし今回は、そのタイムラインに即時性はあまり重要でなく、それよりも断続的に投稿され続ける情報をリアルタイムで眺められるようにしたい、というのが実際にやりたかったことです。

仕組み

ユーザ(クライアント)が POST
    ↓
Rails が受け、 POST 内容を DB に書き込む
    ↓
DB に書き込んだ情報を Firebase に投げる
    ↓
Firebase が受け、クライアントに反映
    ↓
クライアントが Firebase から情報を受け画面に表示

という流れでやっています。
ユーザが Post するのは Rails サーバに対してですが、タイムラインを表示するためにクライアントは Firebase から情報を取得する、という流れになっています。

この流れのメリット

実装の簡略化

Rails 側は WebSocket 周りを何も気にすることがなく、普通に Rest API を作成し、その処理の一部に Firebase に情報を横流しする、というフローが増えるだけです。

クライアント実装が楽に

クライアント側は Firebase SDK を使えば良いため Socket 周りの実装を自力でやる必要がありません。
オフライン時の処理や再接続なども Firebase さんがいい感じにやってくれています。

また、Firebase SDKiOS/Android/JS など幅広く対応されており知見も共有できます。

お金も安い

Firebase Pricing
100 人まで同時接続、データベースは 1 GB まで無料で利用できます。

有料になったとしても $25 per month で 10,000 人 まで同時接続数を増やせますし、同時接続の初期制限値 10,000 を解除できるよう努力しております。 と言っているため今後もっと増えるのではないでしょうか。

スタートアップなどではまず このサービスには価値があるのか というのを検証したいと思うので、ある程度までは無料でまかなえるのは良いのではないでしょうか。

実装

Firebase の設定

Firebase Analytics を iOS / Android アプリに導入する手順のまとめ などを参考に、 Project を作成しましょう。

作成したら Project の作成 -> サービスアカウント -> データベースのシークレット からシークレットを取得します。 このシークレットが冒頭に述べた非推奨となっているところです。

秘密鍵json で管理する方法に変わっているようですので、その鍵で通信できれば同様の方法でいけると思いますが、未検証です。。

Rails 側の設定

gem 'firebase' を Gemfile に書き、 bundle install しましょう。

そしたら、 firebase に送信したい場所で以下を書きます。

  def create
    # DB 登録処理など

    base_uri = 'https://project-xxxxxxxxxx.firebaseio.com/'
    secret_key = 'yyyyyyyyyyyyyyyy'
    firebase = Firebase::Client.new(base_uri, secret_key)
    timeline = {title: "timeline"}
    firebase.push('timeline', timeline)
    render :create, status: :created
  end

わかりやすく create メソッドの中でやっていますが、本来ならば worker などをを使い非同期でやるべき処理です。

結果

f:id:star__hoshi:20161211184252p:plain

データを反映することができました。

最後に

データベースのシークレットを使う方法が非推奨となっており、大変残念な記事となってしまいました 😢。
が、 WebSocket の一つの手段として Firebase は有用だと思います。

特に、サービス立ち上げに時間をかけたくない時など、要件があれば検討してみてください。