RailsのActionCableでリアクティブプログラミング
コメントを投稿したら、いいねをしたら、他の人のブラウザ画面にリアルタイムに反映される
そういうWEBアプリを簡単に作れる仕組みを作りたくて今gem作ってます。
https://github.com/tompng/ar_sync AR(Active Record)Sync 名前は変わるかも)
ActionCableで自前でbroadcast頑張ればできるけど、データ同期するモデルが増えると複雑になって破綻すると思うので、
宣言的に定義しておけば全部うまくやってくれる仕組みが必要なはず。
このgemでできること
- 欲しいJSONデータの形をクライアント側からリクエストできる
- だけどSQLのN+1問題が起きない、または楽に回避できる
- そのデータがRails側のmodelと同期していてリアルタイムに更新されていく
- Vue(もしくはReact)と繋げば、リアルタイムにデータ同期されるWEBアプリの完成
多分、GraphQLやMeteorがやってることに近いかな
Railsと何らかのJSフレームワークを使ってるところに簡単に乗せれるところを目指してます。
使い方
モデルの定義
データ同期するカラムと親子関係を記述
class User < ApplicationRecord has_many :posts sync_self sync_data :name sync_has_many :posts # 逆の関係(sync_parent)も定義する end class Post < ApplicationRecord belongs_to :user sync_self sync_data :title, :body, :created_at, :updated_at, :user sync_parent :user, inverse_of: :posts # sync_has_many :postsの逆 end
API作成
class SyncApiController < ApplicationController include ARSync::ApiControllerConcern api(:profile) { |_params| current_user } api(:user) { |params| User.find params[:id] } api(:post) { |params| Post.find params[:id] } end
さくっとView作成
postsまで、postsについたcommentまで、commentについたいいね数まで、など
任意の深さのデータを要求して、vueに渡すだけ
<script> new ARSyncData({ currentUser: { api: 'profile', query: ['id', 'name', { posts: ['title', 'created_at'] }] } post: { api: 'post', params: { id: 3 }, query: ['title', 'body', 'created_at'] } }).load((vueData) => { new Vue({ el: '#foobar', data: vueData }) }) </script> <div id='foobar'> <h1> {{post.title}} by {{post.user.name}} <small>date: {{post.created_at}}</small> </h1> <p>{{post.body}}</p> <hr> <h2>my posts</h2> <div v-for='post in currentUser.posts'> <a :href="'/posts/' + post.id">{{post.title}}</a> <small>date: {{post.created_at}}</small> <!-- remote: true なformやボタンを足すだけで動く --> <a :href="'/posts/' + post.id" data-remote=true data-method=delete>delete</a> </div> </div>
仕組み
Rails側
ActiveRecordのafter_commitでhookをかけて、
そのデータが必要なクライアントにだけ、データのpatchをActionCable経由でbroadcast
JS側
初期データをAPI経由で読み込んで、ActionCableで必要なkeyだけsubscribe
送られてきたpatchをデータに適用して、最新に保つ
VueやReactがそれを勝手に画面に反映してくれる
デモページ
http://arsyncdemo.herokuapp.com/
2つのウィンドウで開くと、いいねやコメントがリアルタイムに反映される様子が見れます
デモのソースコード
https://github.com/tompng/ar_sync/tree/master/sampleapp
今後
- それ、**でできるよ みたいなのあるのかな?
- 関連してそうなライブラリとか色々調べる
- どうしよう