dexiecable 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +22 -28
- data/lib/dexiecable/active_record_ext.rb +10 -13
- data/lib/dexiecable/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d0959acfdf7865fc834899dd5ec5f14c5fbc85bdbc16a874f269bca2688d2579
|
|
4
|
+
data.tar.gz: 9e1b0ea9fb9a89c8289aa0faa77b47c6cdd09bb6fd336eb14c9292fc7c67d0a1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7106c7ed40f0fcf680109f1f476f4195e911836633766c0706d84852621f8a36b76a7eeaa78b2b9fb09ffa5f750a0147fae11a73fc4d8028e75b00840a77799
|
|
7
|
+
data.tar.gz: 8f78e58b67faef035cf225ce08d79f4ab0b954123fe76385e7f458e995f955f4880827b3c62353b3763ab888b57f47af4d8954978758fb4edbf5e50601d68ec5
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> [!NOTE]
|
|
4
4
|
> DexieCable is NOT a local-first solution, because it lacks the capability to automatically sync updates back to the server (this might be added later). For now, think of it as a real-time local-cache solution. Also, check out this [blog post introducing DexieCable](https://dev.to/buhrmi/real-time-rails-without-turbo-modern-reactive-uis-with-inertia-and-dexiecable-4lge).
|
|
5
5
|
|
|
6
|
-
DexieCable augments ActionCable channels with a query DSL that mirrors the Dexie.js API, letting you push database mutations from the server to the client in real time. It also gives you a [`
|
|
6
|
+
DexieCable augments ActionCable channels with a query DSL that mirrors the Dexie.js API, letting you push database mutations from the server to the client in real time. It also gives you a [`streams_to_dexie`](#streams_to_dexie--automatic-model-syncing) ActiveRecord macro for automatic change syncing.
|
|
7
7
|
|
|
8
8
|
You can run any Dexie table update directly inside a channel:
|
|
9
9
|
|
|
@@ -30,11 +30,11 @@ class NotificationsController < ApplicationController
|
|
|
30
30
|
end
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
An even more convenient way is to use the `
|
|
33
|
+
An even more convenient way is to use the `streams_to_dexie` macro (more info [below](#streams_to_dexie--automatic-model-syncing))
|
|
34
34
|
|
|
35
35
|
```ruby
|
|
36
36
|
class Notification < ApplicationRecord
|
|
37
|
-
|
|
37
|
+
streams_to_dexie via: UserChannel, to: :user
|
|
38
38
|
end
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -48,7 +48,7 @@ Add to your `Gemfile`:
|
|
|
48
48
|
gem "dexiecable"
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
Then `bundle install`. The Railtie automatically extends `ActiveRecord::Base` with `
|
|
51
|
+
Then `bundle install`. The Railtie automatically extends `ActiveRecord::Base` with `streams_to_dexie`.
|
|
52
52
|
|
|
53
53
|
### npm package
|
|
54
54
|
|
|
@@ -131,33 +131,25 @@ UserChannel[current_user]
|
|
|
131
131
|
|
|
132
132
|
The full query chain is serialized as JSON and sent over ActionCable. The JS client replays every method call against the local Dexie database in order.
|
|
133
133
|
|
|
134
|
-
### `
|
|
134
|
+
### `streams_to_dexie` — automatic model syncing
|
|
135
135
|
|
|
136
|
-
Add to any ActiveRecord model.
|
|
137
|
-
|
|
138
|
-
```ruby
|
|
139
|
-
class Message < ApplicationRecord
|
|
140
|
-
syncs_to_dexie via: -> { UserChannel[current_user] }
|
|
141
|
-
end
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
You can also pass a channel class with `to:` to have DexieCable handle the scoping:
|
|
136
|
+
Add to any ActiveRecord model. Just provide the channel class and the broadcast target.
|
|
145
137
|
|
|
146
138
|
```ruby
|
|
147
139
|
class Message < ApplicationRecord
|
|
148
140
|
# Calls send(:receiver), then broadcasts: UserChannel.broadcast_to(receiver, ...)
|
|
149
|
-
|
|
141
|
+
streams_to_dexie via: UserChannel, to: :receiver
|
|
150
142
|
|
|
151
143
|
# String used directly: UserChannel.broadcast_to("global_feed", ...)
|
|
152
|
-
|
|
144
|
+
streams_to_dexie via: UserChannel, to: "global_feed"
|
|
153
145
|
|
|
154
146
|
# Procs are also supported. If an array is returned, multiple broadcasts are made
|
|
155
147
|
# conversation.users.each { |u| UserChannel.broadcast_to(u, ...) }
|
|
156
|
-
|
|
148
|
+
streams_to_dexie via: UserChannel, to: -> { conversation.users }
|
|
157
149
|
end
|
|
158
150
|
```
|
|
159
151
|
|
|
160
|
-
Internally, `
|
|
152
|
+
Internally, `streams_to_dexie` sets up the following ActiveRecord callbacks:
|
|
161
153
|
|
|
162
154
|
| Event | Action |
|
|
163
155
|
|---|---|
|
|
@@ -169,21 +161,23 @@ Internally, `syncs_to_dexie` sets up the following ActiveRecord callbacks:
|
|
|
169
161
|
|
|
170
162
|
| Option | Default | Description |
|
|
171
163
|
|---|---|---|
|
|
172
|
-
| `via:` | *(required)* | A DexieCable channel class
|
|
173
|
-
| `to:` | *(none)* | The stream target passed to `broadcast_to`. Symbol → calls `send`. String → used as-is. Proc → evaluated in record context. Returns a single recipient or collection.
|
|
164
|
+
| `via:` | *(required)* | A DexieCable channel class |
|
|
165
|
+
| `to:` | *(none)* | The stream target passed to `broadcast_to`. Symbol → calls `send`. String → used as-is. Proc → evaluated in record context. Returns a single recipient or collection. |
|
|
174
166
|
| `table:` | model's `table_name` | Override the Dexie table name. A Proc is evaluated in the record's context. |
|
|
175
167
|
| `only:` | `[:create, :update, :destroy]` | Limit which events trigger a sync |
|
|
176
168
|
| `with:` | `:as_json_for_dexie` | Method name (Symbol) or Proc for serializing records |
|
|
177
169
|
| `if:` | *(none)* | Symbol (method name) or Proc — only sync when it returns truthy |
|
|
178
170
|
| `unless:` | *(none)* | Symbol (method name) or Proc — skip sync when it returns truthy |
|
|
179
171
|
|
|
180
|
-
You can combine multiple `
|
|
172
|
+
You can combine multiple `streams_to_dexie` declarations, each with different conditions:
|
|
181
173
|
|
|
182
174
|
```ruby
|
|
183
175
|
class Message < ApplicationRecord
|
|
184
|
-
|
|
185
|
-
syncs_to_dexie via: -> { BoardChannel[board] },
|
|
176
|
+
streams_to_dexie via: UserChannel, to: -> { sender },
|
|
186
177
|
if: :published?
|
|
178
|
+
|
|
179
|
+
streams_to_dexie via: AdminChannel,
|
|
180
|
+
unless: -> { draft? }
|
|
187
181
|
end
|
|
188
182
|
```
|
|
189
183
|
|
|
@@ -194,14 +188,14 @@ Override `as_json_for_dexie` in your model, or use the `with` option to specify
|
|
|
194
188
|
```ruby
|
|
195
189
|
class Message < ApplicationRecord
|
|
196
190
|
# Using the default as_json_for_dexie override:
|
|
197
|
-
|
|
191
|
+
streams_to_dexie via: UserChannel, to: :sender
|
|
198
192
|
|
|
199
193
|
def as_json_for_dexie
|
|
200
194
|
super.merge(room_name: room.name)
|
|
201
195
|
end
|
|
202
196
|
|
|
203
197
|
# Or use a custom serializer method:
|
|
204
|
-
|
|
198
|
+
streams_to_dexie via: AdminChannel, to: :admin,
|
|
205
199
|
with: :admin_payload
|
|
206
200
|
|
|
207
201
|
def admin_payload
|
|
@@ -209,7 +203,7 @@ class Message < ApplicationRecord
|
|
|
209
203
|
end
|
|
210
204
|
|
|
211
205
|
# Or a Proc:
|
|
212
|
-
|
|
206
|
+
streams_to_dexie via: PublicChannel,
|
|
213
207
|
with: -> { { id: id, summary: body.truncate(100) } }
|
|
214
208
|
end
|
|
215
209
|
```
|
|
@@ -255,7 +249,7 @@ dexie.messages.where("room_id").equals(5).add({ id: 1, text: "hello" })
|
|
|
255
249
|
|
|
256
250
|
### Use sequence IDs to avoid data loss
|
|
257
251
|
|
|
258
|
-
A common pattern to avoid data loss during transient disconnections is using sequence IDs to bridge the offline gap. When a connection drops, updates continue on the server. Sending the client’s latest known sequence ID upon reconnect allows the backend to query and stream only the records missed while offline.
|
|
252
|
+
A common pattern to avoid data loss during transient disconnections is using sequence IDs to bridge the offline gap and detect gaps in transmitted records. When a connection drops, updates continue on the server. Sending the client’s latest known sequence ID upon reconnect allows the backend to query and stream only the records missed while offline.
|
|
259
253
|
|
|
260
254
|
To enable this, DexieCable ships its own version of the ActionCable client with one key
|
|
261
255
|
extension: **channel params can be functions**. When a param value is a
|
|
@@ -286,7 +280,7 @@ class RoomChannel < ApplicationChannel:Base
|
|
|
286
280
|
end
|
|
287
281
|
```
|
|
288
282
|
|
|
289
|
-
|
|
283
|
+
To add Sequence IDs, you might want to have look at the [Sequenced](https://github.com/derrickreimer/sequenced). Another option is to use [AnyCable](https://docs.anycable.io/rails/getting_started) since it guarantees deliveries of ActionCable messages.
|
|
290
284
|
|
|
291
285
|
### Multi-user environments
|
|
292
286
|
|
|
@@ -9,19 +9,17 @@ module DexieCable
|
|
|
9
9
|
# DexieCable channel.
|
|
10
10
|
#
|
|
11
11
|
# class Message < ApplicationRecord
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# syncs_to_dexie via: -> { tenant_channel }
|
|
12
|
+
# streams_to_dexie via: UserChannel, to: :sender
|
|
13
|
+
# streams_to_dexie via: UserChannel, to: "global_feed"
|
|
14
|
+
# streams_to_dexie via: UserChannel, to: -> { conversation.users }
|
|
15
|
+
# streams_to_dexie via: PublicChannel
|
|
17
16
|
# end
|
|
18
17
|
#
|
|
19
|
-
# @param via [Class
|
|
20
|
-
# evaluated in record context that returns a channel
|
|
21
|
-
# class or a scoped channel (e.g.
|
|
22
|
-
# +-> { UserChannel[current_user] }+). When +to+
|
|
18
|
+
# @param via [Class] A DexieCable channel class. When +to+
|
|
23
19
|
# is given, each recipient is mapped through
|
|
24
20
|
# +via[to]+ to produce scoped channels.
|
|
21
|
+
# Without +to+, +via+ is used directly as an
|
|
22
|
+
# unscoped channel.
|
|
25
23
|
# @param to [Proc, Symbol, String] A Proc evaluated in record
|
|
26
24
|
# context, a Symbol to call via +send+, or a String
|
|
27
25
|
# used directly as the stream name for +broadcast_to+.
|
|
@@ -38,7 +36,7 @@ module DexieCable
|
|
|
38
36
|
# returns truthy (evaluated in the record's context).
|
|
39
37
|
# @param unless [Symbol, Proc] Skip sync if the given method or proc
|
|
40
38
|
# returns truthy (evaluated in the record's context).
|
|
41
|
-
def
|
|
39
|
+
def streams_to_dexie(via:, to: nil, table: nil, only: nil, with: nil, **options)
|
|
42
40
|
events = Array(only || %i[create update destroy])
|
|
43
41
|
conditions = options.slice(:if, :unless)
|
|
44
42
|
serializer = with || :as_json_for_dexie
|
|
@@ -82,12 +80,11 @@ module DexieCable
|
|
|
82
80
|
private
|
|
83
81
|
|
|
84
82
|
def resolve_channel(via, to = nil)
|
|
85
|
-
channel = via.is_a?(Proc) ? instance_exec(&via) : via
|
|
86
83
|
if to
|
|
87
84
|
recipients = resolve_recipient(to)
|
|
88
|
-
Array(recipients).map { |r|
|
|
85
|
+
Array(recipients).map { |r| via[r] }
|
|
89
86
|
else
|
|
90
|
-
|
|
87
|
+
via
|
|
91
88
|
end
|
|
92
89
|
end
|
|
93
90
|
|
data/lib/dexiecable/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dexiecable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stefan Buhrmester
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
version: '7.0'
|
|
40
40
|
description: DexieCable augments ActionCable channels with a query DSL that mirrors
|
|
41
41
|
the Dexie.js API, letting you push database mutations from the server to the client
|
|
42
|
-
in real time. Includes an ActiveRecord macro (
|
|
42
|
+
in real time. Includes an ActiveRecord macro (streams_to_dexie) for automatic change
|
|
43
43
|
syncing.
|
|
44
44
|
email:
|
|
45
45
|
- stefan@buhrmi.de
|
|
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
75
75
|
- !ruby/object:Gem::Version
|
|
76
76
|
version: '0'
|
|
77
77
|
requirements: []
|
|
78
|
-
rubygems_version: 4.0.
|
|
78
|
+
rubygems_version: 4.0.16
|
|
79
79
|
specification_version: 4
|
|
80
80
|
summary: Run Dexie.js IndexedDB operations from your Rails ActionCable channels.
|
|
81
81
|
test_files: []
|