Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RailsとFirebaseで作るリアルタイムチャット

36427fac78373c2974ba5cb6a3cb5780?s=47 moai
March 26, 2021

 RailsとFirebaseで作るリアルタイムチャット

Railsとfirebaseでどのようにリアルタイムチャットを作ったのかを話します。

36427fac78373c2974ba5cb6a3cb5780?s=128

moai

March 26, 2021
Tweet

Transcript

  1. freee 株式会社
 freee Slide Format RailsとFirebaseで作るリアルタイムチャット


  2. • freee株式会社所属
 • Engineer
 • 開発効率高めるのが好き
 • 趣味はrubocopの適用
 山崎遼介 moai


    Engineer
 2
  3. 3 今日のゴール
 RailsとFirebaseで作るリアルタイムチャットの仕組みを紹介


  4. 4 前提
 作りたい機能、技術stack


  5. 5 プロジェクト管理freee
 • プロジェクトにまつわる業務を楽にしたい


  6. 6 作るモチベーション
 • プロジェクトに関する情報を雑に記録する
 • 経営者 <-> プロジェクトマネージャー 間で気になったことを聞ける


  7. 7 • 


  8. 8 技術スタック:前提
 • Ruby on Rails
 • OpenApi
 • TypeScript


    • React

  9. 9 課題


  10. 10 リアルタイムのチャットをどう作るか?(ざっくり)
 • つまりはポーリングどうするの?
 ◦ ロングポーリング? ◦ 世の中に有るイベントサブスクライブサービス使う? ◦ Firebase?(NEW!)

  11. 11 Firebase使う懸念は?
 • 個人情報はどこに置くのか?
 ◦ Firebaseに個人情報置く? ◦ 置くとするとセキュリティはどう担保する? • Railsとの連携はどうするのか?


    ◦ RailsとID連携? 

  12. 12 Firebase使う懸念は?
 • 個人情報はどこに置くのか?
 ◦ Firebaseに個人情報置く? ◦ 置くとするとセキュリティはどう担保する? • Railsとの連携はどうするのか?


    ◦ RailsとID連携?
  13. 13 どうなったの?


  14. 14 アーキテクチャざっくり
 Data Fetch 
 個人情報のやり取り
 Event Publish
 イベントが
 起こったことだけ


    を通知
 Event Subscribe
 イベントが
 起きたことだけを受 信
 新しい Event 有る?

  15. 15 Rails側擬似コード
 class TimeLineMessage < ApplicationRecord after_create_commit -> { Gcp::Firestore.client.col('timeline_notifications').doc.set(

    identifier: "#{id}-timeline", created_at: Time.current ) } end

  16. 16 firebaseのデータ


  17. 17 JavaScript側擬似コード
 export const ChatContainer = (id) => { 2

    const [timelines, setTimeLines] = React.useState([]); const [latestId, setLatestId] = React.useState(0); 3 const reloadTimeline = (id) => { Api.fetchTimeline(setTimeLines); setLatestId(id);}; 4 const usePushNotification(reloadTimeline) = firestore 5 .collection('timeline_notifications').where('identifier', '==', "${id}-timeline") 6 .limit(1).nSnapshot(querySnapshot => { 7 if( querySnapshot.docs[0].id !== latestId ) reloadTimeline(querySnapshot.docs[0].id); 8 }); 9 React.useEffect(() => { usePushNotification(reloadTimeline) } ); 10 return (<Table rows={timelines} />); }
  18. 18 良かったこと


  19. 19 サブスクライブ処理はfirebaseにおまかせできた
 新しい Event 有る?
 ここはFirebase Client がやってくれる Data Fetch

    
 個人情報のやり取り
 Event Subscribe
 イベントが
 起きたことだけを受 信
 Event Publish
 イベントが
 起こったことだけ
 を通知

  20. 20 フロント側の処理はここだけ
 export const ChatContainer = (id) => { 2

    const [timelines, setTimeLines] = React.useState([]); const [latestId, setLatestId] = React.useState(0); 3 const reloadTimeline = (id) => { Api.fetchTimeline(setTimeLines); setLatestId(id);}; 4 const usePushNotification(reloadTimeline) = firestore 5 .collection('timeline_notifications').where('identifier', '==', "${id}-timeline") 6 .limit(1).nSnapshot(querySnapshot => { 7 if( querySnapshot.docs[0].id !== latestId ) reloadTimeline(querySnapshot.docs[0].id); 8 }); 9 React.useEffect(() => { usePushNotification(reloadTimeline) } ); 10 return (<Table rows={timelines} />); }
  21. 21 Firebaseには顧客情報置かなくて済んだ
 class TimeLineMessage after_create_commit -> { Gcp::Firestore.client.col('timeline_notifications').doc.set( identifier: "#{id}-timeline",

    created_at: Time.current ) } end
 通知イベントのみFirebaseに連携
  22. 22 じつは


  23. 23 社内で先行事例が
 • Takumi Ohashi@_tohashi による
 Firebaseを使ってチャット機能を作る先行事例があった
 


  24. 24 まとめ


  25. 25 まとめ
 • FirebaseをEvent通知だけに限定して使うのはめちゃ良い
 • Railsと一緒に使う場合もそんなに悪くない。
 ◦ ただ、ログイン連携は闇の気配。 


  26. Firebaseはいいね


  27. 27 EOF