cable_ready 5.0.0.pre2 → 5.0.0.pre6

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/Gemfile.lock +75 -71
  4. data/README.md +6 -2
  5. data/app/helpers/cable_ready_helper.rb +15 -2
  6. data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +19 -0
  7. data/app/models/concerns/cable_ready/updatable/collections_registry.rb +33 -0
  8. data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +28 -0
  9. data/app/models/concerns/cable_ready/updatable.rb +98 -0
  10. data/app/models/concerns/extend_has_many.rb +13 -0
  11. data/lib/cable_ready/channels.rb +1 -1
  12. data/lib/cable_ready/compoundable.rb +1 -1
  13. data/lib/cable_ready/config.rb +2 -0
  14. data/lib/cable_ready/operation_builder.rb +6 -9
  15. data/lib/cable_ready/version.rb +1 -1
  16. data/lib/generators/cable_ready/{stream_from_generator.rb → helpers_generator.rb} +1 -1
  17. data/test/dummy/app/channels/application_cable/channel.rb +4 -0
  18. data/test/dummy/app/channels/application_cable/connection.rb +4 -0
  19. data/test/dummy/app/controllers/application_controller.rb +2 -0
  20. data/test/dummy/app/helpers/application_helper.rb +2 -0
  21. data/test/dummy/app/jobs/application_job.rb +7 -0
  22. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  23. data/test/dummy/app/models/application_record.rb +3 -0
  24. data/test/dummy/app/models/global_idable_entity.rb +16 -0
  25. data/test/dummy/app/models/post.rb +4 -0
  26. data/test/dummy/app/models/section.rb +6 -0
  27. data/test/dummy/app/models/team.rb +6 -0
  28. data/test/dummy/app/models/topic.rb +4 -0
  29. data/test/dummy/app/models/user.rb +7 -0
  30. data/test/dummy/config/application.rb +22 -0
  31. data/test/dummy/config/boot.rb +5 -0
  32. data/test/dummy/config/environment.rb +5 -0
  33. data/test/dummy/config/environments/development.rb +76 -0
  34. data/test/dummy/config/environments/production.rb +120 -0
  35. data/test/dummy/config/environments/test.rb +59 -0
  36. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  37. data/test/dummy/config/initializers/assets.rb +12 -0
  38. data/test/dummy/config/initializers/backtrace_silencers.rb +8 -0
  39. data/test/dummy/config/initializers/cable_ready.rb +18 -0
  40. data/test/dummy/config/initializers/content_security_policy.rb +28 -0
  41. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  42. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  43. data/test/dummy/config/initializers/inflections.rb +16 -0
  44. data/test/dummy/config/initializers/mime_types.rb +4 -0
  45. data/test/dummy/config/initializers/permissions_policy.rb +11 -0
  46. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  47. data/test/dummy/config/puma.rb +43 -0
  48. data/test/dummy/config/routes.rb +3 -0
  49. data/test/dummy/db/migrate/20210902154139_create_users.rb +9 -0
  50. data/test/dummy/db/migrate/20210902154153_create_posts.rb +10 -0
  51. data/test/dummy/db/migrate/20210904081930_create_topics.rb +9 -0
  52. data/test/dummy/db/migrate/20210904093607_create_sections.rb +9 -0
  53. data/test/dummy/db/migrate/20210913191735_create_teams.rb +8 -0
  54. data/test/dummy/db/migrate/20210913191759_add_team_reference_to_users.rb +5 -0
  55. data/test/dummy/db/schema.rb +49 -0
  56. data/test/dummy/test/models/post_test.rb +7 -0
  57. data/test/dummy/test/models/section_test.rb +7 -0
  58. data/test/dummy/test/models/team_test.rb +7 -0
  59. data/test/dummy/test/models/topic_test.rb +7 -0
  60. data/test/dummy/test/models/user_test.rb +7 -0
  61. data/test/lib/cable_ready/cable_car_test.rb +5 -5
  62. data/test/lib/cable_ready/compoundable_test.rb +26 -0
  63. data/test/lib/cable_ready/helper_test.rb +25 -0
  64. data/test/lib/cable_ready/identifiable_test.rb +0 -6
  65. data/test/lib/cable_ready/operation_builder_test.rb +26 -48
  66. data/test/lib/cable_ready/updatable_test.rb +112 -0
  67. data/test/test_helper.rb +4 -1
  68. metadata +117 -8
  69. data/cable_ready.gemspec +0 -27
  70. data/package.json +0 -41
  71. data/tags +0 -80
  72. data/yarn.lock +0 -2562
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8bb4eaf8d394d6148e9726fb043dcdd34e3ce9e893b8bfba84a5222481a1c951
4
- data.tar.gz: f57b4d052d2fa2f3236f4d64528a8fd546c3983e567a813730f2480358805be1
3
+ metadata.gz: 1e633a229760759357dc902fb53ffa4da04e52e12cfd85233582d535390c7de9
4
+ data.tar.gz: a8f822e9d0f08c10887fa8e6c6cb87ab1ff000541e6df0e7ff9af03444a70699
5
5
  SHA512:
6
- metadata.gz: 180c342be129e4c747823f9697363e3d8ffe50a58da146a2c1ea85f216018a59e333c44dfb89037e2fa7d6ba5f1f95feee4c4c756da97460ebb7e060b9a8566e
7
- data.tar.gz: 9e0f2341bef2045587c54c2a3edfd38224471c2be3582e4e4fb1e1dfa5587e0a29e8148c650f1e39e26bbe96eede3242921e4dcffbd20a8fc924d184cc04b31d
6
+ metadata.gz: e8ac88d391d85b9e73fbfb07367d903ed3451ce802bf4ca427f26aa852c20fd63e6364a4a3e11b7cacb13e75b3f275767c9c781c268a99f5e31f38ba28059804
7
+ data.tar.gz: 923f8d610451ffbab334e1488c870d7efa4cb6d6c6d19aca3eacccd7c34bb81efa6b76f317930618e0b9e3fca632e99ba0ef5f9a515662139fc7c75a6d79a3f3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## [v5.0.0.pre3](https://github.com/stimulusreflex/cable_ready/tree/v5.0.0.pre3) (2021-08-22)
4
+
5
+ [Full Changelog](https://github.com/stimulusreflex/cable_ready/compare/v5.0.0.pre2...v5.0.0.pre3)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - redirect\_to operation [\#144](https://github.com/stimulusreflex/cable_ready/pull/144) ([leastbad](https://github.com/leastbad))
10
+ - RFC simplifed JSON payload + named batches [\#142](https://github.com/stimulusreflex/cable_ready/pull/142) ([leastbad](https://github.com/leastbad))
11
+
12
+ **Merged pull requests:**
13
+
14
+ - Bump path-parse from 1.0.6 to 1.0.7 [\#143](https://github.com/stimulusreflex/cable_ready/pull/143) ([dependabot[bot]](https://github.com/apps/dependabot))
15
+
16
+ ## [v5.0.0.pre2](https://github.com/stimulusreflex/cable_ready/tree/v5.0.0.pre2) (2021-07-21)
17
+
18
+ [Full Changelog](https://github.com/stimulusreflex/cable_ready/compare/v5.0.0.pre1...v5.0.0.pre2)
19
+
20
+ **Implemented enhancements:**
21
+
22
+ - register a CableReady JSON MIME type [\#140](https://github.com/stimulusreflex/cable_ready/pull/140) ([existentialmutt](https://github.com/existentialmutt))
23
+ - Smart options \(they grow up so fast\) [\#136](https://github.com/stimulusreflex/cable_ready/pull/136) ([leastbad](https://github.com/leastbad))
24
+ - Support `to_dom_selector` for operation selectors [\#135](https://github.com/stimulusreflex/cable_ready/pull/135) ([jaredcwhite](https://github.com/jaredcwhite))
25
+ - dom\_id should always be lowercase [\#129](https://github.com/stimulusreflex/cable_ready/pull/129) ([leastbad](https://github.com/leastbad))
26
+
27
+ **Fixed bugs:**
28
+
29
+ - Improve install experience [\#128](https://github.com/stimulusreflex/cable_ready/pull/128) ([leastbad](https://github.com/leastbad))
30
+
31
+ **Closed issues:**
32
+
33
+ - Idea: ability to pass any object which responds to `to_dom_selector` as a selector [\#134](https://github.com/stimulusreflex/cable_ready/issues/134)
34
+
35
+ **Merged pull requests:**
36
+
37
+ - Bump addressable from 2.7.0 to 2.8.0 [\#141](https://github.com/stimulusreflex/cable_ready/pull/141) ([dependabot[bot]](https://github.com/apps/dependabot))
38
+ - chore: make webpack happy with no sideEffects [\#138](https://github.com/stimulusreflex/cable_ready/pull/138) ([ParamagicDev](https://github.com/ParamagicDev))
39
+
40
+ ## [v5.0.0.pre1](https://github.com/stimulusreflex/cable_ready/tree/v5.0.0.pre1) (2021-06-02)
41
+
42
+ [Full Changelog](https://github.com/stimulusreflex/cable_ready/compare/v5.0.0.pre0...v5.0.0.pre1)
43
+
44
+ **Merged pull requests:**
45
+
46
+ - Include app folder in release [\#133](https://github.com/stimulusreflex/cable_ready/pull/133) ([julianrubisch](https://github.com/julianrubisch))
47
+
3
48
  ## [v5.0.0.pre0](https://github.com/stimulusreflex/cable_ready/tree/v5.0.0.pre0) (2021-05-20)
4
49
 
5
50
  [Full Changelog](https://github.com/stimulusreflex/cable_ready/compare/v4.5.0...v5.0.0.pre0)
data/Gemfile.lock CHANGED
@@ -1,67 +1,67 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cable_ready (5.0.0.pre2)
4
+ cable_ready (5.0.0.pre6)
5
5
  rails (>= 5.2)
6
6
  thread-local (>= 1.1.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actioncable (6.1.4)
12
- actionpack (= 6.1.4)
13
- activesupport (= 6.1.4)
11
+ actioncable (6.1.4.1)
12
+ actionpack (= 6.1.4.1)
13
+ activesupport (= 6.1.4.1)
14
14
  nio4r (~> 2.0)
15
15
  websocket-driver (>= 0.6.1)
16
- actionmailbox (6.1.4)
17
- actionpack (= 6.1.4)
18
- activejob (= 6.1.4)
19
- activerecord (= 6.1.4)
20
- activestorage (= 6.1.4)
21
- activesupport (= 6.1.4)
16
+ actionmailbox (6.1.4.1)
17
+ actionpack (= 6.1.4.1)
18
+ activejob (= 6.1.4.1)
19
+ activerecord (= 6.1.4.1)
20
+ activestorage (= 6.1.4.1)
21
+ activesupport (= 6.1.4.1)
22
22
  mail (>= 2.7.1)
23
- actionmailer (6.1.4)
24
- actionpack (= 6.1.4)
25
- actionview (= 6.1.4)
26
- activejob (= 6.1.4)
27
- activesupport (= 6.1.4)
23
+ actionmailer (6.1.4.1)
24
+ actionpack (= 6.1.4.1)
25
+ actionview (= 6.1.4.1)
26
+ activejob (= 6.1.4.1)
27
+ activesupport (= 6.1.4.1)
28
28
  mail (~> 2.5, >= 2.5.4)
29
29
  rails-dom-testing (~> 2.0)
30
- actionpack (6.1.4)
31
- actionview (= 6.1.4)
32
- activesupport (= 6.1.4)
30
+ actionpack (6.1.4.1)
31
+ actionview (= 6.1.4.1)
32
+ activesupport (= 6.1.4.1)
33
33
  rack (~> 2.0, >= 2.0.9)
34
34
  rack-test (>= 0.6.3)
35
35
  rails-dom-testing (~> 2.0)
36
36
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
37
- actiontext (6.1.4)
38
- actionpack (= 6.1.4)
39
- activerecord (= 6.1.4)
40
- activestorage (= 6.1.4)
41
- activesupport (= 6.1.4)
37
+ actiontext (6.1.4.1)
38
+ actionpack (= 6.1.4.1)
39
+ activerecord (= 6.1.4.1)
40
+ activestorage (= 6.1.4.1)
41
+ activesupport (= 6.1.4.1)
42
42
  nokogiri (>= 1.8.5)
43
- actionview (6.1.4)
44
- activesupport (= 6.1.4)
43
+ actionview (6.1.4.1)
44
+ activesupport (= 6.1.4.1)
45
45
  builder (~> 3.1)
46
46
  erubi (~> 1.4)
47
47
  rails-dom-testing (~> 2.0)
48
48
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
49
- activejob (6.1.4)
50
- activesupport (= 6.1.4)
49
+ activejob (6.1.4.1)
50
+ activesupport (= 6.1.4.1)
51
51
  globalid (>= 0.3.6)
52
- activemodel (6.1.4)
53
- activesupport (= 6.1.4)
54
- activerecord (6.1.4)
55
- activemodel (= 6.1.4)
56
- activesupport (= 6.1.4)
57
- activestorage (6.1.4)
58
- actionpack (= 6.1.4)
59
- activejob (= 6.1.4)
60
- activerecord (= 6.1.4)
61
- activesupport (= 6.1.4)
52
+ activemodel (6.1.4.1)
53
+ activesupport (= 6.1.4.1)
54
+ activerecord (6.1.4.1)
55
+ activemodel (= 6.1.4.1)
56
+ activesupport (= 6.1.4.1)
57
+ activestorage (6.1.4.1)
58
+ actionpack (= 6.1.4.1)
59
+ activejob (= 6.1.4.1)
60
+ activerecord (= 6.1.4.1)
61
+ activesupport (= 6.1.4.1)
62
62
  marcel (~> 1.0.0)
63
63
  mini_mime (>= 1.1.0)
64
- activesupport (6.1.4)
64
+ activesupport (6.1.4.1)
65
65
  concurrent-ruby (~> 1.0, >= 1.0.2)
66
66
  i18n (>= 1.6, < 2)
67
67
  minitest (>= 5.1)
@@ -70,7 +70,7 @@ GEM
70
70
  addressable (2.8.0)
71
71
  public_suffix (>= 2.0.2, < 5.0)
72
72
  ast (2.4.2)
73
- async (1.30.0)
73
+ async (1.30.1)
74
74
  console (~> 1.10)
75
75
  nio4r (~> 2.3)
76
76
  timers (~> 4.1)
@@ -95,7 +95,7 @@ GEM
95
95
  fiber-local
96
96
  crass (1.0.6)
97
97
  erubi (1.10.0)
98
- faraday (1.5.1)
98
+ faraday (1.7.0)
99
99
  faraday-em_http (~> 1.0)
100
100
  faraday-em_synchrony (~> 1.0)
101
101
  faraday-excon (~> 1.1)
@@ -103,6 +103,7 @@ GEM
103
103
  faraday-net_http (~> 1.0)
104
104
  faraday-net_http_persistent (~> 1.1)
105
105
  faraday-patron (~> 1.0)
106
+ faraday-rack (~> 1.0)
106
107
  multipart-post (>= 1.2, < 3)
107
108
  ruby2_keywords (>= 0.0.4)
108
109
  faraday-em_http (1.0.0)
@@ -114,6 +115,7 @@ GEM
114
115
  faraday-net_http (1.0.1)
115
116
  faraday-net_http_persistent (1.2.0)
116
117
  faraday-patron (1.0.0)
118
+ faraday-rack (1.0.0)
117
119
  fiber-local (1.0.0)
118
120
  github_changelog_generator (1.16.4)
119
121
  activesupport
@@ -124,27 +126,27 @@ GEM
124
126
  octokit (~> 4.6)
125
127
  rainbow (>= 2.2.1)
126
128
  rake (>= 10.0)
127
- globalid (0.4.2)
128
- activesupport (>= 4.2.0)
129
+ globalid (0.5.2)
130
+ activesupport (>= 5.0)
129
131
  i18n (1.8.10)
130
132
  concurrent-ruby (~> 1.0)
131
- loofah (2.10.0)
133
+ loofah (2.12.0)
132
134
  crass (~> 1.0.2)
133
135
  nokogiri (>= 1.5.9)
134
136
  magic_frozen_string_literal (1.2.0)
135
137
  mail (2.7.1)
136
138
  mini_mime (>= 0.1.1)
137
- marcel (1.0.1)
139
+ marcel (1.0.2)
138
140
  method_source (0.9.2)
139
- mini_mime (1.1.0)
140
- mini_portile2 (2.5.3)
141
+ mini_mime (1.1.2)
142
+ mini_portile2 (2.6.1)
141
143
  minitest (5.14.4)
142
144
  mocha (1.13.0)
143
145
  multi_json (1.15.0)
144
146
  multipart-post (2.1.1)
145
- nio4r (2.5.7)
146
- nokogiri (1.11.7)
147
- mini_portile2 (~> 2.5.0)
147
+ nio4r (2.5.8)
148
+ nokogiri (1.12.5)
149
+ mini_portile2 (~> 2.6.1)
148
150
  racc (~> 1.4)
149
151
  octokit (4.21.0)
150
152
  faraday (>= 0.9)
@@ -169,29 +171,29 @@ GEM
169
171
  rack (2.2.3)
170
172
  rack-test (1.1.0)
171
173
  rack (>= 1.0, < 3)
172
- rails (6.1.4)
173
- actioncable (= 6.1.4)
174
- actionmailbox (= 6.1.4)
175
- actionmailer (= 6.1.4)
176
- actionpack (= 6.1.4)
177
- actiontext (= 6.1.4)
178
- actionview (= 6.1.4)
179
- activejob (= 6.1.4)
180
- activemodel (= 6.1.4)
181
- activerecord (= 6.1.4)
182
- activestorage (= 6.1.4)
183
- activesupport (= 6.1.4)
174
+ rails (6.1.4.1)
175
+ actioncable (= 6.1.4.1)
176
+ actionmailbox (= 6.1.4.1)
177
+ actionmailer (= 6.1.4.1)
178
+ actionpack (= 6.1.4.1)
179
+ actiontext (= 6.1.4.1)
180
+ actionview (= 6.1.4.1)
181
+ activejob (= 6.1.4.1)
182
+ activemodel (= 6.1.4.1)
183
+ activerecord (= 6.1.4.1)
184
+ activestorage (= 6.1.4.1)
185
+ activesupport (= 6.1.4.1)
184
186
  bundler (>= 1.15.0)
185
- railties (= 6.1.4)
187
+ railties (= 6.1.4.1)
186
188
  sprockets-rails (>= 2.0.0)
187
189
  rails-dom-testing (2.0.3)
188
190
  activesupport (>= 4.2.0)
189
191
  nokogiri (>= 1.6)
190
- rails-html-sanitizer (1.3.0)
192
+ rails-html-sanitizer (1.4.2)
191
193
  loofah (~> 2.3)
192
- railties (6.1.4)
193
- actionpack (= 6.1.4)
194
- activesupport (= 6.1.4)
194
+ railties (6.1.4.1)
195
+ actionpack (= 6.1.4.1)
196
+ activesupport (= 6.1.4.1)
195
197
  method_source
196
198
  rake (>= 0.13)
197
199
  thor (~> 1.0)
@@ -199,16 +201,16 @@ GEM
199
201
  rake (13.0.6)
200
202
  regexp_parser (2.1.1)
201
203
  rexml (3.2.5)
202
- rubocop (1.18.3)
204
+ rubocop (1.18.4)
203
205
  parallel (~> 1.10)
204
206
  parser (>= 3.0.0.0)
205
207
  rainbow (>= 2.2.2, < 4.0)
206
208
  regexp_parser (>= 1.8, < 3.0)
207
209
  rexml
208
- rubocop-ast (>= 1.7.0, < 2.0)
210
+ rubocop-ast (>= 1.8.0, < 2.0)
209
211
  ruby-progressbar (~> 1.7)
210
212
  unicode-display_width (>= 1.4.0, < 3.0)
211
- rubocop-ast (1.8.0)
213
+ rubocop-ast (1.10.0)
212
214
  parser (>= 3.0.1.1)
213
215
  rubocop-performance (1.11.4)
214
216
  rubocop (>= 1.7.0, < 2.0)
@@ -225,8 +227,9 @@ GEM
225
227
  actionpack (>= 4.0)
226
228
  activesupport (>= 4.0)
227
229
  sprockets (>= 3.0.0)
228
- standard (1.1.5)
229
- rubocop (= 1.18.3)
230
+ sqlite3 (1.4.2)
231
+ standard (1.1.7)
232
+ rubocop (= 1.18.4)
230
233
  rubocop-performance (= 1.11.4)
231
234
  standardrb (1.0.0)
232
235
  standard
@@ -252,6 +255,7 @@ DEPENDENCIES
252
255
  pry
253
256
  pry-nav
254
257
  rake
258
+ sqlite3
255
259
  standardrb
256
260
 
257
261
  BUNDLED WITH
data/README.md CHANGED
@@ -2,8 +2,12 @@
2
2
  <img src="https://gitcdn.link/repo/stimulusreflex/cable_ready/master/assets/cable-ready-logo-with-copy.svg" width="360" />
3
3
  <h1 align="center">Welcome to CableReady 👋</h1>
4
4
  <p align="center">
5
- <img src="https://img.shields.io/gem/v/cable_ready.svg?color=red" />
6
- <img src="https://img.shields.io/npm/v/cable_ready.svg?color=blue" />
5
+ <a href="https://rubygems.org/gems/cable_ready">
6
+ <img src="https://img.shields.io/gem/v/cable_ready.svg?color=red" />
7
+ </a>
8
+ <a href="https://www.npmjs.com/package/cable_ready">
9
+ <img src="https://img.shields.io/npm/v/cable_ready.svg?color=blue" />
10
+ </a>
7
11
  <a href="https://www.npmjs.com/package/cable_ready">
8
12
  <img alt="downloads" src="https://img.shields.io/npm/dm/cable_ready.svg?color=blue" target="_blank" />
9
13
  </a>
@@ -4,8 +4,21 @@ module CableReadyHelper
4
4
  include CableReady::Compoundable
5
5
  include CableReady::StreamIdentifier
6
6
 
7
- def stream_from(*keys)
7
+ def stream_from(*keys, html_options: {})
8
+ tag.stream_from(**build_options(*keys, html_options))
9
+ end
10
+
11
+ def updates_for(*keys, url: nil, debounce: nil, html_options: {}, &block)
12
+ options = build_options(*keys, html_options)
13
+ options[:url] = url if url
14
+ options[:debounce] = debounce if debounce
15
+ tag.updates_for(**options) { capture(&block) }
16
+ end
17
+
18
+ private
19
+
20
+ def build_options(*keys, html_options)
8
21
  keys.select!(&:itself)
9
- tag.stream_from(identifier: signed_stream_identifier(compound(keys)))
22
+ {identifier: signed_stream_identifier(compound(keys))}.merge(html_options)
10
23
  end
11
24
  end
@@ -0,0 +1,19 @@
1
+ module CableReady
2
+ module Updatable
3
+ class CollectionUpdatableCallbacks
4
+ def initialize(operation)
5
+ @operation = operation
6
+ end
7
+
8
+ def after_commit(model)
9
+ update_collections(model)
10
+ end
11
+
12
+ private
13
+
14
+ def update_collections(model)
15
+ model.class.cable_ready_collections.broadcast_for!(model, @operation)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ module CableReady
2
+ module Updatable
3
+ class CollectionsRegistry
4
+ def initialize
5
+ @registered_collections = []
6
+ end
7
+
8
+ def register(collection)
9
+ @registered_collections << collection
10
+ end
11
+
12
+ def broadcast_for!(model, operation)
13
+ @registered_collections.select { |c| c[:options][:on].include?(operation) }
14
+ .each do |collection|
15
+ resource = find_resource_for_update(collection, model)
16
+ next if resource.nil?
17
+
18
+ collection[:klass].cable_ready_update_collection(resource, collection[:name]) if collection[:options][:if].call(resource)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def find_resource_for_update(collection, model)
25
+ raise ArgumentError, "Could not find inverse_of for #{collection[:name]}" unless collection[:inverse_association]
26
+
27
+ resource = model
28
+ resource = resource.send(collection[:through_association].underscore) if collection[:through_association]
29
+ resource.send(collection[:inverse_association].underscore)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module CableReady
2
+ module Updatable
3
+ class ModelUpdatableCallbacks
4
+ def initialize(operation, enabled_operations = %i[create update destroy])
5
+ @operation = operation
6
+ @enabled_operations = enabled_operations
7
+ end
8
+
9
+ def after_commit(model)
10
+ return unless @enabled_operations.include?(@operation)
11
+
12
+ send("broadcast_#{@operation}", model)
13
+ end
14
+
15
+ private
16
+
17
+ def broadcast_create(model)
18
+ ActionCable.server.broadcast(model.class, {})
19
+ end
20
+ alias_method :broadcast_destroy, :broadcast_create
21
+
22
+ def broadcast_update(model)
23
+ ActionCable.server.broadcast(model.class, {})
24
+ ActionCable.server.broadcast(model.to_global_id, {})
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CableReady
4
+ module Updatable
5
+ extend ::ActiveSupport::Concern
6
+
7
+ included do |base|
8
+ if base < ActiveRecord::Base
9
+ include ExtendHasMany
10
+
11
+ after_commit CollectionUpdatableCallbacks.new(:create), on: :create
12
+ after_commit CollectionUpdatableCallbacks.new(:update), on: :update
13
+ after_commit CollectionUpdatableCallbacks.new(:destroy), on: :destroy
14
+
15
+ def self.enable_updates(*options)
16
+ options = options.extract_options!
17
+ options = {
18
+ on: [:create, :update, :destroy],
19
+ if: -> { true }
20
+ }.merge(options)
21
+
22
+ enabled_operations = Array(options[:on])
23
+
24
+ after_commit(ModelUpdatableCallbacks.new(:create, enabled_operations), {on: :create, if: options[:if]})
25
+ after_commit(ModelUpdatableCallbacks.new(:update, enabled_operations), {on: :update, if: options[:if]})
26
+ after_commit(ModelUpdatableCallbacks.new(:destroy, enabled_operations), {on: :destroy, if: options[:if]})
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ module ClassMethods
34
+ def has_many(name, scope = nil, **options, &extension)
35
+ option = options.delete(:enable_updates)
36
+ broadcast = option.present?
37
+ result = super
38
+ enrich_association_with_updates(name, option) if broadcast
39
+ result
40
+ end
41
+
42
+ def cable_ready_collections
43
+ @cable_ready_collections ||= CollectionsRegistry.new
44
+ end
45
+
46
+ def cable_ready_update_collection(resource, name)
47
+ identifier = resource.to_global_id.to_s + ":" + name.to_s
48
+ ActionCable.server.broadcast(identifier, {})
49
+ end
50
+
51
+ def enrich_association_with_updates(name, option)
52
+ reflection = reflect_on_association(name)
53
+
54
+ inverse_of = reflection.inverse_of&.name&.to_s
55
+ through_association = nil
56
+
57
+ if reflection.through_reflection?
58
+ inverse_of = reflection.through_reflection.inverse_of&.name&.to_s
59
+ through_association = reflection.through_reflection.name.to_s.singularize
60
+ end
61
+
62
+ options = {
63
+ on: [:create, :update, :destroy],
64
+ if: ->(resource) { true }
65
+ }
66
+
67
+ case option
68
+ when TrueClass
69
+ # proceed!
70
+ when FalseClass
71
+ options[:on] = []
72
+ when Array
73
+ options[:on] = option
74
+ when Symbol
75
+ options[:on] = [option]
76
+ when Hash
77
+ option[:on] = Array(option[:on]) if option[:on]
78
+ options = options.merge!(option)
79
+ when Proc
80
+ options[:if] = option
81
+ else
82
+ raise ArgumentError, "Invalid enable_updates option #{option}"
83
+ end
84
+
85
+ reflection.klass.send(:include, CableReady::Updatable) unless reflection.klass.respond_to?(:cable_ready_collections)
86
+
87
+ reflection.klass.cable_ready_collections.register({
88
+ klass: self,
89
+ foreign_key: reflection.foreign_key,
90
+ name: name,
91
+ inverse_association: inverse_of,
92
+ through_association: through_association,
93
+ options: options
94
+ })
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExtendHasMany
4
+ extend ::ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def has_many(*args, &block)
8
+ options = args.extract_options!
9
+ options[:extend] = Array(options[:extend]).push(ClassMethods)
10
+ super(*args, **options, &block)
11
+ end
12
+ end
13
+ end
@@ -13,7 +13,7 @@ module CableReady
13
13
 
14
14
  def [](*keys)
15
15
  keys.select!(&:itself)
16
- identifier = keys.many? || (keys.one? && keys.first.is_a?(ActiveRecord::Base)) ? compound(keys) : keys.pop
16
+ identifier = keys.many? || (keys.one? && keys.first.respond_to?(:to_global_id)) ? compound(keys) : keys.pop
17
17
  @channels[identifier] ||= CableReady::Channel.new(identifier)
18
18
  end
19
19
 
@@ -4,7 +4,7 @@ module CableReady
4
4
  module Compoundable
5
5
  def compound(keys)
6
6
  keys.map { |key|
7
- key.class < ActiveRecord::Base ? key.to_global_id.to_s : key.to_s
7
+ key.respond_to?(:to_global_id) ? key.to_global_id.to_s : key.to_s
8
8
  }.join(":")
9
9
  end
10
10
  end
@@ -54,6 +54,8 @@ module CableReady
54
54
  outer_html
55
55
  prepend
56
56
  push_state
57
+ redirect_to
58
+ reload
57
59
  remove
58
60
  remove_attribute
59
61
  remove_css_class
@@ -48,7 +48,8 @@ module CableReady
48
48
  @previous_selector = options["selector"]
49
49
  options["selector"] = identifiable?(previous_selector) ? dom_id(previous_selector) : previous_selector
50
50
  end
51
- @enqueued_operations[name.to_s] << options
51
+ options["operation"] = name.to_s.camelize(:lower)
52
+ @enqueued_operations << options
52
53
  self
53
54
  }
54
55
  end
@@ -57,26 +58,22 @@ module CableReady
57
58
  @enqueued_operations.to_json(*args)
58
59
  end
59
60
 
60
- def apply!(operations = "{}")
61
+ def apply!(operations = "[]")
61
62
  operations = begin
62
63
  JSON.parse(operations.is_a?(String) ? operations : operations.to_json)
63
64
  rescue JSON::ParserError
64
65
  {}
65
66
  end
66
- operations.each do |name, operation|
67
- operation.each do |enqueued_operation|
68
- @enqueued_operations[name.to_s] << enqueued_operation
69
- end
70
- end
67
+ @enqueued_operations.push(operations)
71
68
  self
72
69
  end
73
70
 
74
71
  def operations_payload
75
- @enqueued_operations.select { |_, list| list.present? }.deep_transform_keys { |key| key.to_s.camelize(:lower) }
72
+ @enqueued_operations.map { |operation| operation.deep_transform_keys! { |key| key.to_s.camelize(:lower) } }
76
73
  end
77
74
 
78
75
  def reset!
79
- @enqueued_operations = Hash.new { |hash, key| hash[key] = [] }
76
+ @enqueued_operations = []
80
77
  @previous_selector = nil
81
78
  end
82
79
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CableReady
4
- VERSION = "5.0.0.pre2"
4
+ VERSION = "5.0.0.pre6"
5
5
  end
@@ -4,7 +4,7 @@ require "rails/generators"
4
4
  require "fileutils"
5
5
 
6
6
  module CableReady
7
- class StreamFromGenerator < Rails::Generators::Base
7
+ class HelpersGenerator < Rails::Generators::Base
8
8
  desc "Initializes CableReady with a reference to the shared ActionCable consumer"
9
9
  source_root File.expand_path("templates", __dir__)
10
10
 
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Channel < ActionCable::Channel::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Connection < ActionCable::Connection::Base
3
+ end
4
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end