ArSync - Reactive Programming with Ruby on Rails
Frontend JSON data will be synchronized with ActiveRecord.
- Provides an json api with query(shape of the json)
- Send a notificaiton with ActionCable and automaticaly updates the data
Installation
- Add this line to your application's Gemfile:
gem 'ar_sync'
- Run generator
rails g ar_sync:install
Usage
- Define parent, data, has_one, has_many to your models
class User < ApplicationRecord
has_many :posts
...
sync_has_data :id, :name
sync_has_many :posts
end
class Post < ApplicationRecord
belongs_to :user
...
sync_parent :user, inverse_of: :posts
sync_has_data :id, :title, :body, :createdAt, :updatedAt
sync_has_one :user, only: [:id, :name]
end
- Define apis
# app/models/sync_schema.rb
class SyncSchema < ArSync::SyncSchemaBase
# User-defined api
serializer_field :my_simple_profile_api do |current_user|
current_user
end
serializer_field :my_simple_friends_api do |current_user, age:|
current_user.friends.where(age: age)
end
# Reload api (field name = classname, params = `ids:`)
serializer_field :User do |current_user, ids:|
User.where(condition).where id: ids
end
serializer_field :Post do |current_user, ids:|
Post.where(condition).where id: ids
end
end
- Write your view
<!-- if you're using vue -->
<script>
const userModel = new ArSyncModel({
api: 'my_simple_profile_api ',
query: { id: true, name: true, posts: ['title', 'createdAt'] }
})
userModel.onload(() => {
new Vue({ el: '#root', data: { user: userModel.data } })
})
</script>
<div id='root'>
<h1>{{user.name}}'s page</h1>
<ul>
<li v-for='post in user.posts'>
<a :href="'/posts/' + post.id">
{{post.title}}
</a>
<small>date: {{post.createdAt}}</small>
</li>
</ul>
<form action='/posts' data-remote=true method=post>
<input name='post[title]'>
<textarea name=post[body]></textarea>
<input type=submit>
</form>
</div>
Now, your view and ActiveRecord are synchronized.
With typescript
-
Add
"ar_sync": "git://github.com/tompng/ar_sync.git"
to your package.json -
Generate types
rails g ar_sync:types path_to_generated_code_dir/
- Connection Setting
import ArSyncModel from 'path_to_generated_code_dir/ArSyncModel'
import ActionCableAdapter from 'ar_sync/core/ActionCableAdapter'
import * as ActionCable from 'actioncable'
ArSyncModel.setConnectionAdapter(new ActionCableAdapter(ActionCable))
// ArSyncModel.setConnectionAdapter(new MyCustomConnectionAdapter) // If you are using other transports
- Write your components
import { useArSyncModel } from 'path_to_generated_code_dir/hooks'
const HelloComponent: React.FC = () => {
const [user, status] = useArSyncModel({
api: 'my_simple_profile_api',
query: ['id', 'name']
})
// user // => { id: number; name: string } | null
if (!user) return <>loading...</>
// user.id // => number
// user.name // => string
// user.foobar // => compile error
return <h1>Hello, {user.name}!</h1>
}