dexiecable 0.1.2 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc22d844e30147740e885b5959d13a6f42c47ff9551490f4b8e61701b1481676
4
- data.tar.gz: 5d82c9e2f8453aa038db8b7eb5997134e56431da93a62ecb30190e5eebef63a2
3
+ metadata.gz: 8d99eb3ba3c4e24ad9e780707ae8f9a1d7d49dad075e38350851d47a215920ca
4
+ data.tar.gz: 4e9922d041d377b10377db9a2673980523690fe2790f48d4ce04c15b361941dc
5
5
  SHA512:
6
- metadata.gz: 18eb395292b406e4f0cd690eafcf9dc68ac5b39cac89c459e0685c95e7cfe42bd551348c3146df1dcd596405b6198c15ecba41ba9e48abceee8068cd65f020ac
7
- data.tar.gz: b2135050a6a827ac7e0c596ed64ad8d6d568ad6f18d278a6b8c819c464564a110396fc76c597985d1d4cc4e1be2ddd0b4aab1aa9b58fb4a5b1663509a9762a7d
6
+ metadata.gz: 88434bc692480d1624a68d06fd1a8f6d1ada2ecaf59f023fa5168008a14bdcc5c9517e5dfa5e199a33e8053f3d0c5faf41eac8bab80756ad87b392f9f707247b
7
+ data.tar.gz: 3e44885987108b69e7160925fcb5908ac5dafa981557dac7ec46caf2e4faa83efdb777950a9011eb01d5692f6c3dd1241ecfef2d9fd7b74a2c8f2aa35ca29f60
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Run [Dexie.js](https://dexie.org) IndexedDB operations from your Rails ActionCable channels.
4
4
 
5
- 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 `syncs_to_dexie` ActiveRecord macro for automatic change syncing.
5
+ 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 `syncs_to_dexia` ActiveRecord macro for automatic change syncing.
6
6
 
7
7
  You can run any Dexie table update directly inside a channel:
8
8
 
@@ -29,11 +29,11 @@ class NotificationsController < ApplicationController
29
29
  end
30
30
  ```
31
31
 
32
- An even more convenient way is to use the `syncs_to_dexie` macro:
32
+ An even more convenient way is to use the `syncs_to_dexia` macro:
33
33
 
34
34
  ```ruby
35
35
  class Notification < ApplicationRecord
36
- syncs_to_dexie via: -> { UserChannel[user] }
36
+ syncs_to_dexia via: UserChannel, subject: :user
37
37
  end
38
38
  ```
39
39
 
@@ -47,7 +47,7 @@ Add to your `Gemfile`:
47
47
  gem "dexiecable"
48
48
  ```
49
49
 
50
- Then `bundle install`. The Railtie automatically extends `ActiveRecord::Base` with `syncs_to_dexie`.
50
+ Then `bundle install`. The Railtie automatically extends `ActiveRecord::Base` with `syncs_to_dexia`.
51
51
 
52
52
  ### npm package
53
53
 
@@ -123,15 +123,21 @@ UserChannel[current_user]
123
123
 
124
124
  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.
125
125
 
126
- ### `syncs_to_dexie` — automatic model syncing
126
+ ### `syncs_to_dexia` — automatic model syncing
127
127
 
128
- Add to any ActiveRecord model:
128
+ Add to any ActiveRecord model. `subject` is what gets passed to `broadcast_to` as the stream target:
129
129
 
130
130
  ```ruby
131
131
  class Message < ApplicationRecord
132
- syncs_to_dexie via: -> { UserChannel[sender] }
133
- syncs_to_dexie via: -> { UserChannel[receiver] }
134
- syncs_to_dexie via: RoomChannel['public']
132
+ # Calls send(:receiver), then broadcasts: broadcast_to(receiver, ...)
133
+ syncs_to_dexia via: UserChannel, subject: :receiver
134
+
135
+ # String used directly: broadcast_to("global_feed", ...)
136
+ syncs_to_dexia via: UserChannel, subject: "global_feed"
137
+
138
+ # Procs are also supported. If an array is returned, multiple broadcasts are made
139
+ # conversation.users.each { |u| broadcast_to(u, ...) }
140
+ syncs_to_dexia via: UserChannel, subject: -> { conversation.users }
135
141
  end
136
142
  ```
137
143
 
@@ -145,7 +151,8 @@ end
145
151
 
146
152
  | Option | Default | Description |
147
153
  |---|---|---|
148
- | `via:` | *(required)* | Proc (evaluated in record context), or channel instance |
154
+ | `via:` | *(required)* | A DexieCable channel class |
155
+ | `subject:` | *(none)* | The stream target passed to `broadcast_to`. Symbol → calls `send`. String → used as-is. Proc → evaluated in record context. Returns a single subject or collection. |
149
156
  | `table:` | model's `table_name` | Override the Dexie table name. A Proc is evaluated in the record's context. |
150
157
  | `only:` | `[:create, :update, :destroy]` | Limit which events trigger a sync |
151
158
  | `if:` | *(none)* | Symbol (method name) or Proc — only sync when it returns truthy |
@@ -155,10 +162,10 @@ You can combine multiple `syncs_to_dexie` declarations, each with different cond
155
162
 
156
163
  ```ruby
157
164
  class Message < ApplicationRecord
158
- syncs_to_dexie via: -> { UserChannel[sender] },
165
+ syncs_to_dexia via: UserChannel, subject: -> { sender },
159
166
  if: :published?
160
167
 
161
- syncs_to_dexie via: -> { AdminChannel },
168
+ syncs_to_dexia via: AdminChannel,
162
169
  unless: -> { draft? }
163
170
  end
164
171
  ```
@@ -169,7 +176,7 @@ Override `as_json_for_dexie` in your model:
169
176
 
170
177
  ```ruby
171
178
  class Message < ApplicationRecord
172
- syncs_to_dexie via: -> { UserChannel[sender] }
179
+ syncs_to_dexia via: UserChannel, subject: :sender
173
180
 
174
181
  def as_json_for_dexie
175
182
  super.merge(room_name: room.name)
@@ -9,55 +9,66 @@ module DexieCable
9
9
  # DexieCable channel.
10
10
  #
11
11
  # class Message < ApplicationRecord
12
- # syncs_to_dexie via: -> { UserChannel[sender] }
13
- # syncs_to_dexie via: -> { UserChannel[receiver] }
14
- # syncs_to_dexie via: PublicChannel
12
+ # syncs_to_dexia via: UserChannel, subject: :sender
13
+ # syncs_to_dexia via: UserChannel, subject: "global_feed"
14
+ # syncs_to_dexia via: UserChannel, subject: -> { conversation.users }
15
+ # syncs_to_dexia via: PublicChannel
15
16
  # end
16
17
  #
17
- # @param via [Proc, DexieCable] Proc evaluated in record context,
18
- # must return a channel (responds to +table+). A channel
19
- # class/instance can also be passed directly. Skipped if nil.
20
- # @param table [String, Symbol, Proc] Override the Dexie table name
21
- # (defaults to the model's table_name). A Proc is
22
- # evaluated in the record's context.
23
- # @param only [Array<Symbol>] Limit which lifecycle events sync.
24
- # Default: [:create, :update, :destroy].
25
- # @param if [Symbol, Proc] Only sync if the given method or proc
26
- # returns truthy (evaluated in the record's context).
27
- # @param unless [Symbol, Proc] Skip sync if the given method or proc
28
- # returns truthy (evaluated in the record's context).
29
- def syncs_to_dexie(via:, table: nil, only: nil, **options)
18
+ # @param via [Class] A DexieCable channel class. When +subject+
19
+ # is given, each subject is mapped through
20
+ # +via[subject]+ to produce scoped channels.
21
+ # Without +subject+, +via+ is used directly as an
22
+ # unscoped channel.
23
+ # @param subject [Proc, Symbol, String] A Proc evaluated in record
24
+ # context, a Symbol to call via +send+, or a String
25
+ # used directly as the stream name for +broadcast_to+.
26
+ # Must return a single subject or collection of
27
+ # subjects.
28
+ # @param table [String, Symbol, Proc] Override the Dexie table name
29
+ # (defaults to the model's table_name). A Proc is
30
+ # evaluated in the record's context.
31
+ # @param only [Array<Symbol>] Limit which lifecycle events sync.
32
+ # Default: [:create, :update, :destroy].
33
+ # @param if [Symbol, Proc] Only sync if the given method or proc
34
+ # returns truthy (evaluated in the record's context).
35
+ # @param unless [Symbol, Proc] Skip sync if the given method or proc
36
+ # returns truthy (evaluated in the record's context).
37
+ def syncs_to_dexia(via:, subject: nil, table: nil, only: nil, **options)
30
38
  events = Array(only || %i[create update destroy])
31
39
  conditions = options.slice(:if, :unless)
32
40
 
33
41
  @dexie_sync_configs ||= []
34
- @dexie_sync_configs << { via: via, table: table, only: events, **conditions }
42
+ @dexie_sync_configs << { via: via, subject: subject, table: table, only: events, **conditions }
35
43
 
36
44
  if events.include?(:destroy)
37
45
  before_destroy :dexie_sync_before_destroy
38
46
 
39
47
  after_commit on: :destroy, **conditions do
40
- channel = resolve_channel(via)
41
- next unless channel
42
- channel.table(resolve_table(table)).delete(dexie_destroy_id)
48
+ Array(resolve_channel(via, subject)).each do |channel|
49
+ next unless channel
50
+ channel.table(resolve_table(table)).delete(dexie_destroy_id)
51
+ end
43
52
  end
44
53
  end
45
54
 
46
55
  if events.include?(:create)
47
56
  after_commit on: :create, **conditions do
48
- channel = resolve_channel(via)
49
- next unless channel
50
- channel.table(resolve_table(table)).add(as_json_for_dexie)
57
+ Array(resolve_channel(via, subject)).each do |channel|
58
+ next unless channel
59
+ channel.table(resolve_table(table)).add(as_json_for_dexie)
60
+ end
51
61
  end
52
62
  end
53
63
 
54
64
  if events.include?(:update)
55
65
  after_commit on: :update, **conditions do
56
- channel = resolve_channel(via)
57
- next unless channel
66
+ Array(resolve_channel(via, subject)).each do |channel|
67
+ next unless channel
58
68
 
59
- changes = as_json_for_dexie.slice(*saved_changes.keys)
60
- channel.table(resolve_table(table)).update(id, changes)
69
+ changes = as_json_for_dexie.slice(*saved_changes.keys)
70
+ channel.table(resolve_table(table)).update(id, changes)
71
+ end
61
72
  end
62
73
  end
63
74
  end
@@ -65,10 +76,20 @@ module DexieCable
65
76
 
66
77
  private
67
78
 
68
- def resolve_channel(via)
69
- case via
70
- when Proc then instance_exec(&via)
71
- else via
79
+ def resolve_channel(via, subject = nil)
80
+ if subject
81
+ subjects = resolve_subject(subject)
82
+ Array(subjects).map { |s| via[s] }
83
+ else
84
+ via
85
+ end
86
+ end
87
+
88
+ def resolve_subject(subject)
89
+ case subject
90
+ when Proc then instance_exec(&subject)
91
+ when Symbol then send(subject)
92
+ else subject
72
93
  end
73
94
  end
74
95
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DexieCable
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.4"
5
5
  end
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.1.2
4
+ version: 0.1.4
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 (syncs_to_dexie) for automatic change
42
+ in real time. Includes an ActiveRecord macro (syncs_to_dexia) for automatic change
43
43
  syncing.
44
44
  email:
45
45
  - stefan@buhrmi.de