cable_ready 5.0.0.pre2 → 5.0.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
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