turbo_chat 0.1.3 → 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 +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +107 -179
- data/app/assets/config/turbo_chat_manifest.js +1 -0
- data/app/assets/javascripts/turbo_chat/application.js +1 -0
- data/app/assets/javascripts/turbo_chat/invite_picker.js +767 -0
- data/app/assets/javascripts/turbo_chat/lifecycle_events.js +13 -0
- data/app/assets/javascripts/turbo_chat/realtime.js +28 -0
- data/app/assets/javascripts/turbo_chat/shared.js +19 -3
- data/app/assets/stylesheets/turbo_chat/application.css +595 -14
- data/app/controllers/turbo_chat/chat_memberships_controller.rb +49 -1
- data/app/controllers/turbo_chat/chat_messages_controller.rb +18 -1
- data/app/controllers/turbo_chat/chats_controller.rb +38 -1
- data/app/helpers/turbo_chat/application_helper/config_support.rb +26 -0
- data/app/helpers/turbo_chat/application_helper/mention_support.rb +7 -0
- data/app/helpers/turbo_chat/application_helper/participant_support.rb +28 -0
- data/app/models/turbo_chat/chat.rb +1 -1
- data/app/models/turbo_chat/chat_membership.rb +13 -0
- data/app/models/turbo_chat/chat_message/broadcasting.rb +6 -2
- data/app/models/turbo_chat/chat_message/signals.rb +1 -1
- data/app/models/turbo_chat/chat_message.rb +83 -2
- data/app/views/layouts/turbo_chat/application.html.erb +1 -0
- data/app/views/turbo_chat/chat_messages/_form.html.erb +51 -2
- data/app/views/turbo_chat/chat_messages/_system.html.erb +8 -0
- data/app/views/turbo_chat/chats/_invite_form.html.erb +28 -0
- data/app/views/turbo_chat/chats/_member_entries.html.erb +120 -0
- data/app/views/turbo_chat/chats/index.html.erb +8 -2
- data/app/views/turbo_chat/chats/show.html.erb +62 -18
- data/config/routes.rb +1 -1
- data/lib/generators/turbo_chat/install/templates/turbo_chat.rb +89 -18
- data/lib/turbo_chat/configuration/blocked_words_support.rb +41 -0
- data/lib/turbo_chat/configuration/defaults.rb +95 -0
- data/lib/turbo_chat/configuration/emoji_support.rb +40 -0
- data/lib/turbo_chat/configuration/role_support.rb +32 -0
- data/lib/turbo_chat/configuration.rb +14 -238
- data/lib/turbo_chat/engine.rb +1 -0
- data/lib/turbo_chat/moderation/chat_actions.rb +44 -0
- data/lib/turbo_chat/moderation/member_actions.rb +76 -0
- data/lib/turbo_chat/moderation/support.rb +87 -0
- data/lib/turbo_chat/moderation.rb +9 -191
- data/lib/turbo_chat/permission/mention_support.rb +20 -0
- data/lib/turbo_chat/permission/support.rb +63 -0
- data/lib/turbo_chat/permission.rb +54 -179
- data/lib/turbo_chat/version.rb +1 -1
- data/turbo_chat.gemspec +3 -2
- metadata +18 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87e5b68d4722dd1f28ae30a9926da8445184f2c3116b66f55c8f948e15e923f8
|
|
4
|
+
data.tar.gz: 4654ef43284576a86f56c64c24d93bf3f6a15da709a81720af9fe38f331f5d6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cfa9becf70f4e79fb3d5907dacefd722e87849b8f0cb3cbc75a6b7baa82680bdee3dc82b9d600bf4ddaee56ceaddbb278611a70b462bf8ff1604947f536e951
|
|
7
|
+
data.tar.gz: b5e6106acb66c2e01447ef4a2b104d28da4206a712bf42a3076f5b981e3165d388e787b2307d70793d89ff550cfefdf73dceaea9e100b7ee50489d3284c8eda0
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `turbo_chat` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.4] - 2026-02-22
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Searchable invite picker for chat invitations.
|
|
9
|
+
- Collapsible members panel with fixed-height member list shell.
|
|
10
|
+
- Role management and Turbo member list synchronization in chat UI.
|
|
11
|
+
- Lifecycle system messages for join/leave/moderation events.
|
|
12
|
+
- Config toggles for chat member visibility and composer controls.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Expanded initializer template guidance and README setup/docs.
|
|
16
|
+
- Refactored core chat modules for simpler internal structure.
|
|
17
|
+
- Improved invite row UX and chat composer behavior.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Turbo Stream helper errors in member entry rendering.
|
|
21
|
+
- CI setup to prepare the test database before running `test:all`.
|
|
22
|
+
|
|
23
|
+
## [0.1.3] - 2026-02-19
|
|
24
|
+
- Initial RubyGems release.
|
data/README.md
CHANGED
|
@@ -1,65 +1,45 @@
|
|
|
1
1
|
# TurboChat
|
|
2
2
|
|
|
3
|
-
TurboChat is a mountable Rails chat engine for server-rendered
|
|
3
|
+
TurboChat is a mountable Rails chat engine for server-rendered applications.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Turbo Stream chat UI.
|
|
7
|
-
- Role-based permissions.
|
|
8
|
-
- Mentions, typing signals, invites, moderation.
|
|
9
|
-
- Practical customization hooks without rewriting everything.
|
|
5
|
+
Status: actively maintained.
|
|
10
6
|
|
|
11
|
-
What
|
|
12
|
-
- A hosted chat service.
|
|
13
|
-
- A React-first component library.
|
|
14
|
-
- A "just add JS" widget.
|
|
7
|
+
## What You Get
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
- Turbo Stream chat UI.
|
|
10
|
+
- Role-based permissions.
|
|
11
|
+
- Mentions, invitations, moderation, and typing signals.
|
|
12
|
+
- A Rails-first path to ship chat quickly.
|
|
19
13
|
|
|
20
|
-
|
|
14
|
+
## Basic Setup
|
|
21
15
|
|
|
22
|
-
|
|
16
|
+
Add the gem:
|
|
23
17
|
|
|
24
18
|
```ruby
|
|
25
19
|
# Gemfile
|
|
26
20
|
gem "turbo_chat"
|
|
27
21
|
```
|
|
28
22
|
|
|
23
|
+
Install and migrate:
|
|
24
|
+
|
|
29
25
|
```bash
|
|
30
26
|
bundle install
|
|
31
27
|
bin/rails generate turbo_chat:install
|
|
32
28
|
bin/rails db:migrate
|
|
33
29
|
```
|
|
34
30
|
|
|
35
|
-
Mount
|
|
31
|
+
Mount the engine:
|
|
36
32
|
|
|
37
33
|
```ruby
|
|
38
34
|
# config/routes.rb
|
|
39
|
-
mount TurboChat::Engine => "/
|
|
35
|
+
mount TurboChat::Engine => "/", as: "turbo_chat"
|
|
40
36
|
```
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
## Participant Resolution (Most Important Section)
|
|
45
|
-
|
|
46
|
-
This is where installs usually fail. TurboChat now resolves the current participant in this order:
|
|
38
|
+
This gives you chat routes like `/` (chat index), `/chats`, and `/chats/:id`.
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
2. `config.current_participant_resolver` (custom resolver lambda).
|
|
50
|
-
3. `current_user` (if your app exposes it).
|
|
40
|
+
## Host App Requirements
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Return value must be:
|
|
55
|
-
- `nil` (unauthenticated), or
|
|
56
|
-
- a model that uses `acts_as_chat_participant`.
|
|
57
|
-
|
|
58
|
-
If you use Devise and your `User` model is a chat participant, this works out of the box.
|
|
59
|
-
|
|
60
|
-
## Host Contract
|
|
61
|
-
|
|
62
|
-
### Participant model opt-in
|
|
42
|
+
### 1. Mark your participant model
|
|
63
43
|
|
|
64
44
|
```ruby
|
|
65
45
|
class User < ApplicationRecord
|
|
@@ -67,7 +47,11 @@ class User < ApplicationRecord
|
|
|
67
47
|
end
|
|
68
48
|
```
|
|
69
49
|
|
|
70
|
-
###
|
|
50
|
+
### 2. Resolve the current participant
|
|
51
|
+
|
|
52
|
+
Define `current_chat_participant` in your host `ApplicationController`.
|
|
53
|
+
|
|
54
|
+
Recommended hook:
|
|
71
55
|
|
|
72
56
|
```ruby
|
|
73
57
|
class ApplicationController < ActionController::Base
|
|
@@ -77,7 +61,12 @@ class ApplicationController < ActionController::Base
|
|
|
77
61
|
end
|
|
78
62
|
```
|
|
79
63
|
|
|
80
|
-
|
|
64
|
+
Fallback behavior (only if you do not define `current_chat_participant`):
|
|
65
|
+
|
|
66
|
+
1. `config.current_participant_resolver`
|
|
67
|
+
2. `current_user`
|
|
68
|
+
|
|
69
|
+
Optional resolver for non-`current_user` auth:
|
|
81
70
|
|
|
82
71
|
```ruby
|
|
83
72
|
TurboChat.configure do |config|
|
|
@@ -85,35 +74,24 @@ TurboChat.configure do |config|
|
|
|
85
74
|
end
|
|
86
75
|
```
|
|
87
76
|
|
|
88
|
-
## First Working
|
|
77
|
+
## First Working Example
|
|
78
|
+
|
|
79
|
+
Create a chat and add an admin membership:
|
|
89
80
|
|
|
90
81
|
```ruby
|
|
91
82
|
chat = TurboChat::Chat.create!(title: "Support")
|
|
92
83
|
TurboChat::ChatMembership.create!(chat: chat, participant: current_user, role: :admin)
|
|
93
84
|
```
|
|
94
85
|
|
|
86
|
+
Link to it:
|
|
87
|
+
|
|
95
88
|
```erb
|
|
96
89
|
<%= link_to "Open chat", turbo_chat.chat_path(chat) %>
|
|
97
90
|
```
|
|
98
91
|
|
|
99
|
-
##
|
|
100
|
-
|
|
101
|
-
From the mounted engine:
|
|
102
|
-
- `GET /chats`
|
|
103
|
-
- `GET /chats/:id`
|
|
104
|
-
- `POST /chats`
|
|
105
|
-
- `PATCH /chats/:id/accept`
|
|
106
|
-
- `PATCH /chats/:id/decline`
|
|
107
|
-
- `PATCH /chats/:id/leave`
|
|
108
|
-
- `PATCH /chats/:id/close`
|
|
109
|
-
- `PATCH /chats/:id/reopen`
|
|
110
|
-
- `POST /chats/:chat_id/chat_memberships`
|
|
111
|
-
- `POST /chats/:chat_id/chat_messages`
|
|
112
|
-
- `PATCH /chats/:chat_id/chat_messages/:id`
|
|
113
|
-
|
|
114
|
-
## Recommended Baseline Config
|
|
92
|
+
## Essential Configuration
|
|
115
93
|
|
|
116
|
-
|
|
94
|
+
Start with a minimal initializer and only expand when needed:
|
|
117
95
|
|
|
118
96
|
```ruby
|
|
119
97
|
TurboChat.configure do |config|
|
|
@@ -122,11 +100,8 @@ TurboChat.configure do |config|
|
|
|
122
100
|
config.max_chat_participants = 10
|
|
123
101
|
config.max_message_length = 1000
|
|
124
102
|
config.message_history_limit = 200
|
|
125
|
-
config.active_chat_window = 5.minutes
|
|
126
103
|
|
|
127
104
|
config.enable_mentions = true
|
|
128
|
-
config.mention_filter_exclude_self = true
|
|
129
|
-
config.mention_filter_hide_roles = true
|
|
130
105
|
config.enable_emoji_aliases = true
|
|
131
106
|
|
|
132
107
|
config.blocked_words = []
|
|
@@ -136,38 +111,25 @@ TurboChat.configure do |config|
|
|
|
136
111
|
config.show_timestamp = true
|
|
137
112
|
config.show_role = false
|
|
138
113
|
|
|
139
|
-
config.emit_typing_events = false
|
|
140
|
-
config.emit_message_events = false
|
|
141
|
-
config.emit_mention_events = false
|
|
142
|
-
config.emit_invitation_events = false
|
|
143
|
-
config.emit_chat_lifecycle_events = false
|
|
144
114
|
config.emit_moderation_events = false
|
|
145
115
|
config.emit_blocked_words_events = false
|
|
116
|
+
config.emit_mention_events = false
|
|
146
117
|
end
|
|
147
118
|
```
|
|
148
119
|
|
|
149
|
-
|
|
150
|
-
- Leave HTML rendering off unless required.
|
|
151
|
-
- Leave event emission off unless consumed.
|
|
152
|
-
- Keep permissions adapter default until you have a concrete policy gap.
|
|
153
|
-
|
|
154
|
-
## Roles and Permissions
|
|
120
|
+
## Roles
|
|
155
121
|
|
|
156
122
|
Built-in roles:
|
|
123
|
+
|
|
157
124
|
- `member`
|
|
158
125
|
- `moderator`
|
|
159
126
|
- `admin`
|
|
160
127
|
|
|
161
|
-
|
|
162
|
-
- `member`: view/post and member mentions.
|
|
163
|
-
- `moderator`: invite, `@all`, role mentions, mute/timeout/ban, delete lower-rank messages.
|
|
164
|
-
- `admin`: moderator powers plus close/reopen chat.
|
|
128
|
+
Role behavior:
|
|
165
129
|
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
- Closed chat blocks posting.
|
|
170
|
-
- Muted/timed-out members cannot post.
|
|
130
|
+
- `member`: can view/post and mention members.
|
|
131
|
+
- `moderator`: can invite, mention `@all`/roles, mute/timeout/ban, and delete lower-rank messages.
|
|
132
|
+
- `admin`: can do moderator actions plus close/reopen chats.
|
|
171
133
|
|
|
172
134
|
Custom role example:
|
|
173
135
|
|
|
@@ -182,53 +144,11 @@ TurboChat.configure do |config|
|
|
|
182
144
|
end
|
|
183
145
|
```
|
|
184
146
|
|
|
185
|
-
## Invitations
|
|
186
|
-
|
|
187
|
-
- Invite creation: `POST /chats/:chat_id/chat_memberships`
|
|
188
|
-
- Accept: `PATCH /chats/:id/accept`
|
|
189
|
-
- Decline: `PATCH /chats/:id/decline`
|
|
190
|
-
|
|
191
|
-
Important constraints:
|
|
192
|
-
- Invite type must match inviter participant base class.
|
|
193
|
-
- Participant limits apply to active memberships.
|
|
194
|
-
- Re-invite reactivates existing memberships.
|
|
195
|
-
|
|
196
|
-
## Messages, Mentions, Signals
|
|
197
|
-
|
|
198
|
-
### Messages
|
|
199
|
-
- Realtime append/update/remove via Turbo Streams.
|
|
200
|
-
- Inline edit for your own messages (permission-gated).
|
|
201
|
-
- History capped by `message_history_limit`.
|
|
202
|
-
|
|
203
|
-
### Mentions
|
|
204
|
-
- `@username`, `@all`, `@ROLE`.
|
|
205
|
-
- Server-side mention permission validation.
|
|
206
|
-
- Autocomplete defaults: excludes self, hides roles.
|
|
207
|
-
|
|
208
|
-
### Signals
|
|
209
|
-
Automatic typing loop is built in.
|
|
210
|
-
|
|
211
|
-
Manual APIs:
|
|
212
|
-
|
|
213
|
-
```ruby
|
|
214
|
-
TurboChat::Signals.start!(chat: chat, participant: current_user, signal_type: :thinking)
|
|
215
|
-
TurboChat::Signals.replace!(chat: chat, participant: current_user, signal_type: :planning)
|
|
216
|
-
TurboChat::Signals.clear!(chat: chat, participant: current_user)
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
```ruby
|
|
220
|
-
TurboChat::Signals.with(chat: chat, participant: current_user, signal_type: :thinking) do
|
|
221
|
-
# work
|
|
222
|
-
end
|
|
223
|
-
```
|
|
224
|
-
|
|
225
147
|
## Moderation API
|
|
226
148
|
|
|
227
149
|
```ruby
|
|
228
150
|
TurboChat::Moderation.mute_member!(actor: moderator, membership: membership)
|
|
229
|
-
TurboChat::Moderation.unmute_member!(actor: moderator, membership: membership)
|
|
230
151
|
TurboChat::Moderation.timeout_member!(actor: moderator, membership: membership, until_time: 30.minutes.from_now)
|
|
231
|
-
TurboChat::Moderation.clear_timeout!(actor: moderator, membership: membership)
|
|
232
152
|
TurboChat::Moderation.ban_member!(actor: moderator, membership: membership)
|
|
233
153
|
TurboChat::Moderation.delete_message!(actor: moderator, message: message)
|
|
234
154
|
TurboChat::Moderation.close_chat!(actor: admin, chat: chat)
|
|
@@ -236,74 +156,89 @@ TurboChat::Moderation.reopen_chat!(actor: admin, chat: chat)
|
|
|
236
156
|
```
|
|
237
157
|
|
|
238
158
|
Raises:
|
|
159
|
+
|
|
239
160
|
- `TurboChat::Moderation::AuthorizationError`
|
|
240
161
|
- `TurboChat::Moderation::InvalidActionError`
|
|
241
162
|
|
|
242
|
-
##
|
|
243
|
-
|
|
244
|
-
Enable with config flags.
|
|
245
|
-
|
|
246
|
-
Event names:
|
|
247
|
-
- `turbo-chat:typing-started`
|
|
248
|
-
- `turbo-chat:typing-ended`
|
|
249
|
-
- `turbo-chat:message-sent`
|
|
250
|
-
- `turbo-chat:mention`
|
|
251
|
-
- `turbo-chat:invitation-accepted`
|
|
252
|
-
- `turbo-chat:chat-invited`
|
|
253
|
-
- `turbo-chat:chat-joined`
|
|
254
|
-
- `turbo-chat:chat-declined`
|
|
255
|
-
- `turbo-chat:chat-left`
|
|
256
|
-
- `turbo-chat:chat-closed`
|
|
257
|
-
- `turbo-chat:chat-reopened`
|
|
163
|
+
## Signals API
|
|
258
164
|
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
});
|
|
165
|
+
```ruby
|
|
166
|
+
TurboChat::Signals.start!(chat: chat, participant: current_user, signal_type: :typing)
|
|
167
|
+
TurboChat::Signals.clear!(chat: chat, participant: current_user)
|
|
263
168
|
```
|
|
264
169
|
|
|
265
|
-
|
|
170
|
+
## Event Emissions
|
|
266
171
|
|
|
267
|
-
|
|
172
|
+
All event emissions are opt-in.
|
|
268
173
|
|
|
269
|
-
|
|
270
|
-
- `turbo_chat.moderation.member_muted`
|
|
271
|
-
- `turbo_chat.moderation.member_unmuted`
|
|
272
|
-
- `turbo_chat.moderation.member_timed_out`
|
|
273
|
-
- `turbo_chat.moderation.member_timeout_cleared`
|
|
274
|
-
- `turbo_chat.moderation.member_banned`
|
|
275
|
-
- `turbo_chat.moderation.message_deleted`
|
|
276
|
-
- `turbo_chat.moderation.chat_closed`
|
|
277
|
-
- `turbo_chat.moderation.chat_reopened`
|
|
174
|
+
Enable only what you consume:
|
|
278
175
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
176
|
+
```ruby
|
|
177
|
+
TurboChat.configure do |config|
|
|
178
|
+
config.emit_typing_events = true
|
|
179
|
+
config.emit_message_events = true
|
|
180
|
+
config.emit_mention_events = true
|
|
181
|
+
config.emit_invitation_events = true
|
|
182
|
+
config.emit_chat_lifecycle_events = true
|
|
183
|
+
config.emit_moderation_events = true
|
|
184
|
+
config.emit_blocked_words_events = true
|
|
185
|
+
end
|
|
186
|
+
```
|
|
283
187
|
|
|
284
|
-
|
|
188
|
+
Browser events (`CustomEvent`):
|
|
285
189
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
190
|
+
- `emit_typing_events`: `turbo-chat:typing-started`, `turbo-chat:typing-ended`
|
|
191
|
+
- `emit_message_events`: `turbo-chat:message-sent`
|
|
192
|
+
- `emit_mention_events`: `turbo-chat:mention`
|
|
193
|
+
- `emit_invitation_events`: `turbo-chat:invitation-accepted`
|
|
194
|
+
- `emit_chat_lifecycle_events`: `turbo-chat:chat-invited`, `turbo-chat:chat-joined`, `turbo-chat:chat-declined`, `turbo-chat:chat-left`, `turbo-chat:chat-closed`, `turbo-chat:chat-reopened`
|
|
290
195
|
|
|
291
|
-
|
|
292
|
-
- `app/views/turbo_chat/chat_messages/_message.html.erb`
|
|
196
|
+
Minimal browser listener:
|
|
293
197
|
|
|
294
|
-
|
|
198
|
+
```js
|
|
199
|
+
[
|
|
200
|
+
"turbo-chat:typing-started",
|
|
201
|
+
"turbo-chat:typing-ended",
|
|
202
|
+
"turbo-chat:message-sent",
|
|
203
|
+
"turbo-chat:mention",
|
|
204
|
+
"turbo-chat:invitation-accepted",
|
|
205
|
+
"turbo-chat:chat-invited",
|
|
206
|
+
"turbo-chat:chat-joined",
|
|
207
|
+
"turbo-chat:chat-declined",
|
|
208
|
+
"turbo-chat:chat-left",
|
|
209
|
+
"turbo-chat:chat-closed",
|
|
210
|
+
"turbo-chat:chat-reopened"
|
|
211
|
+
].forEach(function (eventName) {
|
|
212
|
+
document.addEventListener(eventName, function (event) {
|
|
213
|
+
console.log(eventName, event.detail);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
```
|
|
295
217
|
|
|
296
|
-
|
|
218
|
+
Server-side notifications (`ActiveSupport::Notifications`):
|
|
297
219
|
|
|
298
|
-
|
|
220
|
+
- `emit_moderation_events`:
|
|
221
|
+
`turbo_chat.moderation.member_muted`,
|
|
222
|
+
`turbo_chat.moderation.member_unmuted`,
|
|
223
|
+
`turbo_chat.moderation.member_timed_out`,
|
|
224
|
+
`turbo_chat.moderation.member_timeout_cleared`,
|
|
225
|
+
`turbo_chat.moderation.member_banned`,
|
|
226
|
+
`turbo_chat.moderation.message_deleted`,
|
|
227
|
+
`turbo_chat.moderation.chat_closed`,
|
|
228
|
+
`turbo_chat.moderation.chat_reopened`
|
|
229
|
+
- `emit_blocked_words_events`:
|
|
230
|
+
`turbo_chat.blocked_words.detected`,
|
|
231
|
+
`turbo_chat.blocked_words.rejected`,
|
|
232
|
+
`turbo_chat.blocked_words.scrambled`
|
|
299
233
|
|
|
300
|
-
|
|
301
|
-
- Engine namespace in source: `TurboChat`
|
|
302
|
-
- Database table prefix: `turbo_chat_`
|
|
303
|
-
- Browser event prefix: `turbo-chat:*`
|
|
304
|
-
- `ActiveSupport::Notifications` prefix: `turbo_chat.*`
|
|
234
|
+
Minimal Rails listener:
|
|
305
235
|
|
|
306
|
-
|
|
236
|
+
```ruby
|
|
237
|
+
ActiveSupport::Notifications.subscribe(/turbo_chat\.(moderation|blocked_words)\./) do |*args|
|
|
238
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
239
|
+
Rails.logger.info("[TurboChat] #{event.name} #{event.payload.inspect}")
|
|
240
|
+
end
|
|
241
|
+
```
|
|
307
242
|
|
|
308
243
|
## Upgrade
|
|
309
244
|
|
|
@@ -317,10 +252,3 @@ bin/rails db:migrate
|
|
|
317
252
|
- Ruby `>= 3.1`
|
|
318
253
|
- Rails `>= 7.0`, `< 8.0`
|
|
319
254
|
- `turbo-rails` `>= 1.4`, `< 3.0`
|
|
320
|
-
- PostgreSQL or SQLite
|
|
321
|
-
|
|
322
|
-
## Development
|
|
323
|
-
|
|
324
|
-
```bash
|
|
325
|
-
bundle exec rake test
|
|
326
|
-
```
|