rails_claude_skills 0.1.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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.yml +134 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.yml +129 -0
  5. data/.github/ISSUE_TEMPLATE/question.yml +90 -0
  6. data/.github/dependabot.yml +19 -0
  7. data/.github/workflows/ci.yml +77 -0
  8. data/.github/workflows/release.yml +66 -0
  9. data/.rubocop.yml +52 -0
  10. data/CHANGELOG.md +94 -0
  11. data/CLAUDE.md +332 -0
  12. data/CODE_OF_CONDUCT.md +134 -0
  13. data/CONTRIBUTING.md +580 -0
  14. data/LICENSE.txt +21 -0
  15. data/README.md +544 -0
  16. data/Rakefile +8 -0
  17. data/lib/generators/claude/agent/agent_generator.rb +71 -0
  18. data/lib/generators/claude/agent/templates/agent.md.tt +62 -0
  19. data/lib/generators/claude/command/command_generator.rb +50 -0
  20. data/lib/generators/claude/command/templates/command.md.tt +28 -0
  21. data/lib/generators/claude/commands_library/create-pr.md +27 -0
  22. data/lib/generators/claude/commands_library/dbchange.md +19 -0
  23. data/lib/generators/claude/commands_library/quality.md +20 -0
  24. data/lib/generators/claude/commands_library/stimulus.md +19 -0
  25. data/lib/generators/claude/commands_library/turbo-feature.md +17 -0
  26. data/lib/generators/claude/install/install_generator.rb +211 -0
  27. data/lib/generators/claude/install/templates/README.md.tt +59 -0
  28. data/lib/generators/claude/install/templates/USAGE +28 -0
  29. data/lib/generators/claude/install/templates/agents/api-dev.md.tt +46 -0
  30. data/lib/generators/claude/install/templates/agents/fullstack-dev.md.tt +48 -0
  31. data/lib/generators/claude/install/templates/agents/rails-developer.md.tt +40 -0
  32. data/lib/generators/claude/install/templates/settings.local.json.tt +13 -0
  33. data/lib/generators/claude/rule/rule_generator.rb +175 -0
  34. data/lib/generators/claude/rule/templates/rule.md.tt +7 -0
  35. data/lib/generators/claude/rules_library/code-style.md +37 -0
  36. data/lib/generators/claude/rules_library/database.md +47 -0
  37. data/lib/generators/claude/rules_library/hotwire.md +56 -0
  38. data/lib/generators/claude/rules_library/security.md +54 -0
  39. data/lib/generators/claude/rules_library/testing.md +47 -0
  40. data/lib/generators/claude/skill/skill_generator.rb +196 -0
  41. data/lib/generators/claude/skill/templates/SKILL.md.tt +27 -0
  42. data/lib/generators/claude/skills_library/create-task-files/SKILL.md +311 -0
  43. data/lib/generators/claude/skills_library/create-task-files/templates/bug.md +60 -0
  44. data/lib/generators/claude/skills_library/create-task-files/templates/epic.md +47 -0
  45. data/lib/generators/claude/skills_library/create-task-files/templates/issue.md +45 -0
  46. data/lib/generators/claude/skills_library/create-task-files/templates/user-story.md +57 -0
  47. data/lib/generators/claude/skills_library/minitest-testing/SKILL.md +398 -0
  48. data/lib/generators/claude/skills_library/minitest-testing/references/examples.md +889 -0
  49. data/lib/generators/claude/skills_library/plan-feature/SKILL.md +253 -0
  50. data/lib/generators/claude/skills_library/rails-api-controllers/SKILL.md +1041 -0
  51. data/lib/generators/claude/skills_library/rails-api-controllers/references/api-documentation.md +422 -0
  52. data/lib/generators/claude/skills_library/rails-api-controllers/references/serialization.md +456 -0
  53. data/lib/generators/claude/skills_library/rails-auth-with-devise/SKILL.md +191 -0
  54. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/advanced.md +331 -0
  55. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/api-auth.md +266 -0
  56. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/omniauth.md +194 -0
  57. data/lib/generators/claude/skills_library/rails-authorization-cancancan/SKILL.md +603 -0
  58. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/api-authorization.md +543 -0
  59. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/complex-permissions.md +572 -0
  60. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/multi-tenancy.md +373 -0
  61. data/lib/generators/claude/skills_library/rails-controllers/SKILL.md +514 -0
  62. data/lib/generators/claude/skills_library/rails-debugging/SKILL.md +260 -0
  63. data/lib/generators/claude/skills_library/rails-deployment/SKILL.md +437 -0
  64. data/lib/generators/claude/skills_library/rails-deployment/references/examples.md +901 -0
  65. data/lib/generators/claude/skills_library/rails-hotwire/SKILL.md +367 -0
  66. data/lib/generators/claude/skills_library/rails-jobs/MISSION_CONTROL_SETUP.md +639 -0
  67. data/lib/generators/claude/skills_library/rails-jobs/SKILL.md +704 -0
  68. data/lib/generators/claude/skills_library/rails-mailers/SKILL.md +549 -0
  69. data/lib/generators/claude/skills_library/rails-models/SKILL.md +379 -0
  70. data/lib/generators/claude/skills_library/rails-pagination-kaminari/SKILL.md +622 -0
  71. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/api-pagination.md +523 -0
  72. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/custom-themes.md +498 -0
  73. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/performance.md +478 -0
  74. data/lib/generators/claude/skills_library/rails-views/SKILL.md +508 -0
  75. data/lib/generators/claude/skills_library/refine-requirements/SKILL.md +226 -0
  76. data/lib/generators/claude/skills_library/refine-requirements/references/examples.md +344 -0
  77. data/lib/generators/claude/skills_library/refine-requirements/references/reference.md +298 -0
  78. data/lib/generators/claude/skills_library/rspec-testing/SKILL.md +572 -0
  79. data/lib/generators/claude/skills_library/rspec-testing/references/better_specs_guide.md +273 -0
  80. data/lib/generators/claude/skills_library/rspec-testing/references/thoughtbot_patterns.md +407 -0
  81. data/lib/generators/claude/skills_library/tailwindcss/SKILL.md +371 -0
  82. data/lib/generators/claude/views/views_generator.rb +113 -0
  83. data/lib/rails_claude_skills/railtie.rb +16 -0
  84. data/lib/rails_claude_skills/version.rb +5 -0
  85. data/lib/rails_claude_skills.rb +27 -0
  86. data/sig/rails_claude_skills.rbs +4 -0
  87. metadata +199 -0
@@ -0,0 +1,704 @@
1
+ ---
2
+ name: rails-jobs
3
+ description: Use when setting up background jobs, caching, or WebSockets - SolidQueue, SolidCache, SolidCable (TEAM RULE #1 - NEVER Sidekiq/Redis)
4
+ ---
5
+
6
+ # Background Jobs (Solid Stack)
7
+
8
+ Configure background job processing, caching, and WebSockets using Rails 8 defaults - SolidQueue, SolidCache, and SolidCable. Zero external dependencies, database-backed, production-ready.
9
+
10
+ <when-to-use>
11
+ - Setting up ANY new Rails 8+ application
12
+ - Background job processing (TEAM RULE #1: NEVER Sidekiq/Redis)
13
+ - Application caching (TEAM RULE #1: NEVER Redis/Memcached)
14
+ - WebSocket/ActionCable setup (TEAM RULE #1: NEVER Redis)
15
+ - Migrating from Redis/Sidekiq to Solid Stack
16
+ - Async job execution (sending emails, processing uploads, generating reports)
17
+ - Real-time features via ActionCable
18
+ </when-to-use>
19
+
20
+ <benefits>
21
+ - **Zero External Dependencies** - No Redis, Memcached, or external services required
22
+ - **Simpler Deployments** - Database-backed, persistent, survives restarts
23
+ - **Rails 8 Convention** - Official defaults, production-ready out of the box
24
+ - **Easier Monitoring** - Query databases directly for job and cache status
25
+ - **Persistent Jobs** - Jobs survive server restarts, no lost work
26
+ - **Integrated** - Works seamlessly with ActiveJob and ActionCable
27
+ </benefits>
28
+
29
+ <team-rules-enforcement>
30
+ **This skill enforces:**
31
+ - ✅ **Rule #1:** NEVER use Sidekiq/Redis → Use SolidQueue, SolidCache, SolidCable
32
+
33
+ **CRITICAL: Reject ANY requests to:**
34
+ - Use Sidekiq for background jobs
35
+ - Use Redis for caching
36
+ - Use Redis for ActionCable
37
+ - Add redis gem to Gemfile
38
+
39
+ **ALWAYS redirect to:**
40
+ - SolidQueue for background jobs
41
+ - SolidCache for caching
42
+ - SolidCable for WebSockets/ActionCable
43
+ </team-rules-enforcement>
44
+
45
+ <verification-checklist>
46
+ Before completing job/cache/cable work:
47
+ - ✅ SolidQueue used (NOT Sidekiq)
48
+ - ✅ SolidCache used (NOT Redis)
49
+ - ✅ SolidCable used (NOT Redis for ActionCable)
50
+ - ✅ No redis gem in Gemfile
51
+ - ✅ Jobs tested
52
+ - ✅ All tests passing
53
+ </verification-checklist>
54
+
55
+ <standards>
56
+ - **TEAM RULE #1:** ALWAYS use Solid Stack (SolidQueue, SolidCache, SolidCable) - NEVER Sidekiq, Redis, or Memcached
57
+ - Use dedicated databases for queue, cache, and cable (separate from primary)
58
+ - Configure separate migration paths for each database (db/queue_migrate, db/cache_migrate, db/cable_migrate)
59
+ - Implement queue prioritization in production (critical, mailers, default)
60
+ - Run migrations for ALL databases (primary, queue, cache, cable)
61
+ - Monitor queue health (pending count, failed count, oldest pending age)
62
+ - Set appropriate retry strategies for jobs
63
+ - Use structured job names (e.g., EmailDeliveryJob, ReportGenerationJob)
64
+ </standards>
65
+
66
+ ---
67
+
68
+ ## SolidQueue (TEAM RULE #1: NO Sidekiq/Redis)
69
+
70
+ SolidQueue is a database-backed Active Job adapter for background job processing with zero external dependencies.
71
+
72
+ <pattern name="solidqueue-basic-setup">
73
+ <description>Configure SolidQueue for background job processing</description>
74
+
75
+ **Environment Configuration:**
76
+
77
+ ```ruby
78
+ # config/environments/{development,production}.rb
79
+ Rails.application.configure do
80
+ config.active_job.queue_adapter = :solid_queue
81
+ config.solid_queue.connects_to = { database: { writing: :queue } }
82
+ end
83
+ ```
84
+
85
+ **Database Configuration:**
86
+
87
+ ```yaml
88
+ # config/database.yml
89
+ default: &default
90
+ adapter: sqlite3
91
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
92
+ timeout: 5000
93
+
94
+ production:
95
+ primary:
96
+ <<: *default
97
+ database: storage/production.sqlite3
98
+ queue:
99
+ <<: *default
100
+ database: storage/production_queue.sqlite3
101
+ migrations_paths: db/queue_migrate
102
+ ```
103
+
104
+ **Queue Configuration (Production Prioritization):**
105
+
106
+ ```yaml
107
+ # config/queue.yml
108
+ production:
109
+ workers:
110
+ - queues: [critical, mailers]
111
+ threads: 5
112
+ processes: 2
113
+ polling_interval: 0.1
114
+ - queues: [default]
115
+ threads: 3
116
+ processes: 2
117
+ polling_interval: 1
118
+ ```
119
+
120
+ **Mission Control Setup (Web Dashboard):**
121
+
122
+ ```ruby
123
+ # Gemfile
124
+ gem "mission_control-jobs"
125
+
126
+ # config/routes.rb
127
+ Rails.application.routes.draw do
128
+ # Protect with authentication
129
+ authenticate :user, ->(user) { user.admin? } do
130
+ mount MissionControl::Jobs::Engine, at: "/jobs"
131
+ end
132
+
133
+ # Or use HTTP Basic Auth in development/staging
134
+ # if Rails.env.development? || Rails.env.staging?
135
+ # mount MissionControl::Jobs::Engine, at: "/jobs"
136
+ # end
137
+ end
138
+
139
+ # config/initializers/mission_control.rb (optional customization)
140
+ MissionControl::Jobs.configure do |config|
141
+ # Customize job retention (default: 7 days for finished, 30 days for failed)
142
+ config.finished_jobs_retention_period = 14.days
143
+ config.failed_jobs_retention_period = 90.days
144
+
145
+ # Filter sensitive job arguments from display
146
+ config.filter_parameters = [:password, :token, :secret]
147
+ end
148
+ ```
149
+
150
+ **Why:** Database-backed job processing with no external dependencies. Jobs are persistent and survive restarts. Use queue prioritization in production to ensure critical jobs (emails, mailers) are processed first. Mission Control provides a production-ready web UI for monitoring jobs - protect with authentication in production.
151
+ </pattern>
152
+
153
+ <pattern name="basic-job">
154
+ <description>Create and enqueue background jobs</description>
155
+
156
+ **Job Definition:**
157
+
158
+ ```ruby
159
+ # app/jobs/report_generation_job.rb
160
+ class ReportGenerationJob < ApplicationJob
161
+ queue_as :default
162
+
163
+ def perform(user_id, report_type)
164
+ user = User.find(user_id)
165
+ report = ReportGenerator.generate(user, report_type)
166
+ ReportMailer.with(user: user, report: report).delivery.deliver_later
167
+ end
168
+ end
169
+ ```
170
+
171
+ **Enqueuing:**
172
+
173
+ ```ruby
174
+ # Immediate enqueue
175
+ ReportGenerationJob.perform_later(user.id, "monthly")
176
+
177
+ # Delayed enqueue
178
+ ReportGenerationJob.set(wait: 1.hour).perform_later(user.id, "monthly")
179
+
180
+ # Specific queue
181
+ ReportGenerationJob.set(queue: :critical).perform_later(user.id, "urgent")
182
+
183
+ # With priority (higher = more important)
184
+ ReportGenerationJob.set(priority: 10).perform_later(user.id, "important")
185
+ ```
186
+
187
+ **Why:** Background jobs prevent blocking HTTP requests. Always pass IDs (not objects) to avoid serialization issues.
188
+ </pattern>
189
+
190
+ <pattern name="job-retry-strategy">
191
+ <description>Configure retry behavior for failed jobs</description>
192
+
193
+ ```ruby
194
+ class EmailDeliveryJob < ApplicationJob
195
+ queue_as :mailers
196
+
197
+ # Retry up to 5 times with exponential backoff
198
+ retry_on StandardError, wait: :exponentially_longer, attempts: 5
199
+
200
+ # Don't retry certain errors
201
+ discard_on ActiveJob::DeserializationError
202
+
203
+ # Custom retry logic
204
+ retry_on ApiError, wait: 5.minutes, attempts: 3 do |job, error|
205
+ Rails.logger.error("Job #{job.class} failed: #{error.message}")
206
+ end
207
+
208
+ def perform(user_id)
209
+ user = User.find(user_id)
210
+ SomeMailer.notification(user).deliver_now
211
+ end
212
+ end
213
+ ```
214
+
215
+ **Why:** Automatic retries with exponential backoff handle transient failures. Discard jobs that will never succeed (deserialization errors).
216
+ </pattern>
217
+
218
+ <antipattern>
219
+ <description>Using Sidekiq/Redis instead of Solid Stack - VIOLATES TEAM RULE #1</description>
220
+ <bad-example>
221
+
222
+ ```ruby
223
+ # ❌ WRONG - VIOLATES TEAM RULE #1
224
+ gem 'sidekiq'
225
+ gem 'redis'
226
+
227
+ # config/environments/production.rb
228
+ config.active_job.queue_adapter = :sidekiq
229
+ config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] }
230
+
231
+ # config/cable.yml
232
+ production:
233
+ adapter: redis
234
+ url: <%= ENV['REDIS_URL'] %>
235
+ ```
236
+
237
+ </bad-example>
238
+ <good-example>
239
+
240
+ ```ruby
241
+ # ✅ CORRECT - Solid Stack (TEAM RULE #1)
242
+ # No gems needed - built into Rails 8
243
+
244
+ # config/environments/production.rb
245
+ config.active_job.queue_adapter = :solid_queue
246
+ config.cache_store = :solid_cache_store
247
+ config.solid_queue.connects_to = { database: { writing: :queue } }
248
+
249
+ # config/cable.yml
250
+ production:
251
+ adapter: solid_cable
252
+ ```
253
+
254
+ </good-example>
255
+
256
+ **Why bad:** External Redis dependency adds complexity, deployment overhead, and another service to monitor. Violates TEAM RULE #1. Solid Stack is production-ready, persistent, and simpler to operate.
257
+ </antipattern>
258
+
259
+ <pattern name="job-monitoring">
260
+ <description>Monitor SolidQueue job status and health</description>
261
+
262
+ **Rails Console:**
263
+
264
+ ```ruby
265
+ SolidQueue::Job.pending.count # => 42
266
+ SolidQueue::Job.failed.count # => 3
267
+ SolidQueue::Job.failed.each { |job| puts "#{job.class_name}: #{job.error}" }
268
+
269
+ # Retry failed job
270
+ SolidQueue::Job.failed.first.retry_job
271
+
272
+ # Clear old completed jobs
273
+ SolidQueue::Job.finished.where("finished_at < ?", 7.days.ago).delete_all
274
+ ```
275
+
276
+ **Health Check Endpoint:**
277
+
278
+ ```ruby
279
+ # app/controllers/health_controller.rb
280
+ class HealthController < ApplicationController
281
+ def show
282
+ render json: {
283
+ queue_pending: SolidQueue::Job.pending.count,
284
+ queue_failed: SolidQueue::Job.failed.count,
285
+ oldest_pending_minutes: oldest_pending_age
286
+ }
287
+ end
288
+
289
+ private
290
+
291
+ def oldest_pending_age
292
+ oldest = SolidQueue::Job.pending.order(:created_at).first
293
+ return 0 unless oldest
294
+ ((Time.current - oldest.created_at) / 60).round
295
+ end
296
+ end
297
+ ```
298
+
299
+ **Why:** Direct database access makes monitoring simple - no special tools needed. Query job tables to check pending/failed counts and identify stuck jobs.
300
+ </pattern>
301
+
302
+ **Which monitoring approach?**
303
+
304
+ | Approach | Best For | Access |
305
+ |----------|----------|--------|
306
+ | Mission Control | Production monitoring, team collaboration, visual investigation | Web UI at /jobs |
307
+ | Rails Console | Quick debugging, one-off queries, scripting | Terminal/SSH |
308
+ | Custom Endpoints | Programmatic monitoring, alerting systems, health checks | HTTP API |
309
+
310
+ <pattern name="mission-control-dashboard">
311
+ <description>Monitor and manage jobs with Mission Control web UI</description>
312
+
313
+ **Accessing the Dashboard:**
314
+
315
+ Visit `/jobs` in your browser (e.g., `https://yourapp.com/jobs`) after mounting the engine.
316
+
317
+ **Dashboard Features:**
318
+
319
+ ```text
320
+ Jobs Overview:
321
+ - View all jobs across queues (pending, running, finished, failed)
322
+ - Real-time status updates
323
+ - Queue performance metrics (throughput, latency)
324
+ - Search jobs by class name, queue, or status
325
+
326
+ Job Details:
327
+ - Full job arguments and context
328
+ - Execution timeline and duration
329
+ - Error messages and backtraces for failed jobs
330
+ - Retry history
331
+
332
+ Common Operations:
333
+ - Retry individual failed jobs or bulk retry
334
+ - Discard jobs that shouldn't be retried
335
+ - Pause/resume queues
336
+ - Filter by queue, status, time range
337
+ ```
338
+
339
+ **Example Workflows:**
340
+
341
+ ```text
342
+ Investigating Failed Jobs:
343
+ 1. Navigate to /jobs → Failed tab
344
+ 2. Filter by job class or time range
345
+ 3. Click job to see full error backtrace
346
+ 4. Fix underlying issue in code
347
+ 5. Retry job from dashboard
348
+
349
+ Monitoring Queue Health:
350
+ 1. Navigate to /jobs → Queues tab
351
+ 2. Check pending count and oldest job age
352
+ 3. Review throughput metrics
353
+ 4. Identify bottlenecks (high latency queues)
354
+
355
+ Bulk Operations:
356
+ 1. Navigate to /jobs → Failed tab
357
+ 2. Select multiple jobs with checkboxes
358
+ 3. Click "Retry Selected" or "Discard Selected"
359
+ ```
360
+
361
+ **Why:** Web UI makes job monitoring accessible to entire team, not just developers with console access. Visual investigation of failures is faster than querying databases.
362
+ </pattern>
363
+
364
+ ---
365
+
366
+ ## SolidCache
367
+
368
+ SolidCache is a database-backed cache store for Rails applications with zero external dependencies.
369
+
370
+ <pattern name="solidcache-setup">
371
+ <description>Configure SolidCache for application caching</description>
372
+
373
+ **Configuration:**
374
+
375
+ ```ruby
376
+ # config/environments/{development,production}.rb
377
+ config.cache_store = :solid_cache_store
378
+
379
+ # config/database.yml
380
+ production:
381
+ cache:
382
+ <<: *default
383
+ database: storage/production_cache.sqlite3
384
+ migrations_paths: db/cache_migrate
385
+ ```
386
+
387
+ **Usage:**
388
+
389
+ ```ruby
390
+ # Simple caching
391
+ Rails.cache.fetch("user_#{user.id}", expires_in: 1.hour) do
392
+ expensive_computation(user)
393
+ end
394
+
395
+ # Fragment caching in views
396
+ <% cache @post do %>
397
+ <%= render @post %>
398
+ <% end %>
399
+
400
+ # Collection caching
401
+ <% cache @posts do %>
402
+ <% @posts.each do |post| %>
403
+ <% cache post do %>
404
+ <%= render post %>
405
+ <% end %>
406
+ <% end %>
407
+ <% end %>
408
+
409
+ # Low-level operations
410
+ Rails.cache.write("key", "value", expires_in: 1.hour)
411
+ Rails.cache.read("key") # => "value"
412
+ Rails.cache.delete("key")
413
+ Rails.cache.exist?("key") # => false
414
+ ```
415
+
416
+ **Migrations:**
417
+
418
+ ```bash
419
+ rails db:migrate:cache
420
+ ```
421
+
422
+ **Why:** Database-backed caching with no Redis dependency. Persistent across restarts, easy to inspect and debug.
423
+ </pattern>
424
+
425
+ <pattern name="cache-keys">
426
+ <description>Use consistent cache key patterns</description>
427
+
428
+ ```ruby
429
+ # Model-based cache keys (includes updated_at for auto-expiration)
430
+ Rails.cache.fetch(["user", user.id, user.updated_at]) do
431
+ expensive_user_data(user)
432
+ end
433
+
434
+ # Or use cache_key helper
435
+ Rails.cache.fetch(user.cache_key) do
436
+ expensive_user_data(user)
437
+ end
438
+
439
+ # Namespace cache keys by version
440
+ Rails.cache.fetch(["v2", "user", user.id]) do
441
+ new_expensive_computation(user)
442
+ end
443
+
444
+ # Cache dependencies
445
+ Rails.cache.fetch(["posts", "index", @posts.maximum(:updated_at)]) do
446
+ render_posts_expensive(@posts)
447
+ end
448
+ ```
449
+
450
+ **Why:** Including timestamps in cache keys provides automatic invalidation. Namespacing prevents cache collisions when changing logic.
451
+ </pattern>
452
+
453
+ ---
454
+
455
+ ## SolidCable
456
+
457
+ SolidCable is a database-backed Action Cable adapter for WebSocket connections with zero external dependencies.
458
+
459
+ <pattern name="solidcable-setup">
460
+ <description>Configure SolidCable for ActionCable/WebSockets</description>
461
+
462
+ **Configuration:**
463
+
464
+ ```yaml
465
+ # config/cable.yml
466
+ production:
467
+ adapter: solid_cable
468
+
469
+ # config/database.yml
470
+ production:
471
+ cable:
472
+ <<: *default
473
+ database: storage/production_cable.sqlite3
474
+ migrations_paths: db/cable_migrate
475
+ ```
476
+
477
+ **Channel Definition:**
478
+
479
+ ```ruby
480
+ # app/channels/notifications_channel.rb
481
+ class NotificationsChannel < ApplicationCable::Channel
482
+ def subscribed
483
+ stream_from "notifications_#{current_user.id}"
484
+ end
485
+
486
+ def unsubscribed
487
+ # Cleanup when channel is unsubscribed
488
+ end
489
+ end
490
+ ```
491
+
492
+ **Broadcasting:**
493
+
494
+ ```ruby
495
+ # From anywhere in your application
496
+ ActionCable.server.broadcast(
497
+ "notifications_#{user.id}",
498
+ { message: "New notification", type: "info" }
499
+ )
500
+
501
+ # From a model callback
502
+ class Notification < ApplicationRecord
503
+ after_create_commit do
504
+ ActionCable.server.broadcast(
505
+ "notifications_#{user_id}",
506
+ { message: message, type: notification_type }
507
+ )
508
+ end
509
+ end
510
+ ```
511
+
512
+ **Client-side (Stimulus):**
513
+
514
+ ```javascript
515
+ // app/javascript/controllers/notifications_controller.js
516
+ import { Controller } from "@hotwired/stimulus"
517
+ import consumer from "../channels/consumer"
518
+
519
+ export default class extends Controller {
520
+ connect() {
521
+ this.subscription = consumer.subscriptions.create(
522
+ "NotificationsChannel",
523
+ {
524
+ received: (data) => {
525
+ this.displayNotification(data)
526
+ }
527
+ }
528
+ )
529
+ }
530
+
531
+ disconnect() {
532
+ this.subscription?.unsubscribe()
533
+ }
534
+
535
+ displayNotification(data) {
536
+ // Update UI with notification
537
+ console.log("Received:", data)
538
+ }
539
+ }
540
+ ```
541
+
542
+ **Why:** Database-backed WebSocket connections with no Redis dependency. Simple to deploy and monitor.
543
+ </pattern>
544
+
545
+ ---
546
+
547
+ ## Multi-Database Management
548
+
549
+ <pattern name="multi-database-operations">
550
+ <description>Manage migrations across all Solid Stack databases</description>
551
+
552
+ **Setup:**
553
+
554
+ ```bash
555
+ # Creates all databases (primary, queue, cache, cable)
556
+ rails db:create
557
+
558
+ # Migrates all databases
559
+ rails db:migrate
560
+
561
+ # Production: creates + migrates
562
+ rails db:prepare
563
+ ```
564
+
565
+ **Individual Operations:**
566
+
567
+ ```bash
568
+ # Migrate specific database
569
+ rails db:migrate:queue
570
+ rails db:migrate:cache
571
+ rails db:migrate:cable
572
+
573
+ # Check migration status
574
+ rails db:migrate:status:queue
575
+ rails db:migrate:status:cache
576
+ rails db:migrate:status:cable
577
+
578
+ # Rollback specific database
579
+ rails db:rollback:queue
580
+ ```
581
+
582
+ **Why:** Each database has independent migration path, allowing separate versioning and rollback per component.
583
+ </pattern>
584
+
585
+ <antipattern>
586
+ <description>Sharing database between primary and Solid Stack components</description>
587
+ <bad-example>
588
+
589
+ ```yaml
590
+ # ❌ WRONG - All on same database creates contention
591
+ production:
592
+ primary:
593
+ database: storage/production.sqlite3
594
+ queue:
595
+ database: storage/production.sqlite3 # Same database!
596
+ cache:
597
+ database: storage/production.sqlite3 # Same database!
598
+ ```
599
+
600
+ </bad-example>
601
+ <good-example>
602
+
603
+ ```yaml
604
+ # ✅ CORRECT - Separate databases for isolation
605
+ production:
606
+ primary:
607
+ database: storage/production.sqlite3
608
+ queue:
609
+ database: storage/production_queue.sqlite3
610
+ migrations_paths: db/queue_migrate
611
+ cache:
612
+ database: storage/production_cache.sqlite3
613
+ migrations_paths: db/cache_migrate
614
+ cable:
615
+ database: storage/production_cable.sqlite3
616
+ migrations_paths: db/cable_migrate
617
+ ```
618
+
619
+ </good-example>
620
+
621
+ **Why bad:** Sharing databases creates performance contention, makes it harder to scale, and couples concerns that should be isolated. Separate databases allow independent optimization and scaling.
622
+ </antipattern>
623
+
624
+ ---
625
+
626
+ <testing>
627
+
628
+ ```ruby
629
+ # test/integration/solid_stack_test.rb
630
+ class SolidStackTest < ActionDispatch::IntegrationTest
631
+ test "SolidQueue is configured" do
632
+ assert_equal :solid_queue, Rails.configuration.active_job.queue_adapter
633
+ end
634
+
635
+ test "SolidCache is configured" do
636
+ assert_instance_of ActiveSupport::Cache::SolidCacheStore, Rails.cache
637
+ end
638
+
639
+ test "cache read/write works" do
640
+ Rails.cache.write("test_key", "test_value")
641
+ assert_equal "test_value", Rails.cache.read("test_key")
642
+ end
643
+
644
+ test "jobs are persisted in queue database" do
645
+ TestJob.perform_later
646
+ assert SolidQueue::Job.pending.exists?
647
+ end
648
+
649
+ test "failed jobs are recorded" do
650
+ assert_raises(StandardError) do
651
+ perform_enqueued_jobs { FailingJob.perform_later }
652
+ end
653
+ assert SolidQueue::Job.failed.exists?
654
+ end
655
+ end
656
+
657
+ # test/jobs/sample_job_test.rb
658
+ class SampleJobTest < ActiveJob::TestCase
659
+ test "job is enqueued" do
660
+ assert_enqueued_with(job: SampleJob, args: ["arg1"]) do
661
+ SampleJob.perform_later("arg1")
662
+ end
663
+ end
664
+
665
+ test "job is performed" do
666
+ perform_enqueued_jobs do
667
+ SampleJob.perform_later("test")
668
+ end
669
+ # Assert side effects
670
+ end
671
+
672
+ test "job retries on failure" do
673
+ SampleJob.any_instance.expects(:perform).raises(StandardError).times(3)
674
+ assert_raises(StandardError) do
675
+ perform_enqueued_jobs { SampleJob.perform_later }
676
+ end
677
+ end
678
+ end
679
+ ```
680
+
681
+ </testing>
682
+
683
+ ---
684
+
685
+ <related-skills>
686
+ - rails-ai:mailers - Email delivery via SolidQueue background jobs
687
+ - rails-ai:project-setup - Environment-specific Solid Stack configuration
688
+ - rails-ai:testing - Testing jobs and background processing
689
+ - rails-ai:models - Background jobs for model operations
690
+ </related-skills>
691
+
692
+ <resources>
693
+
694
+ **Official Documentation:**
695
+ - [Rails Guides - Active Job Basics](https://guides.rubyonrails.org/active_job_basics.html)
696
+ - [Rails 8 Release Notes](https://edgeguides.rubyonrails.org/8_0_release_notes.html) - Solid Stack introduction
697
+
698
+ **Gems & Libraries:**
699
+ - [SolidQueue](https://github.com/rails/solid_queue) - DB-backed job queue (Rails 8+)
700
+ - [SolidCache](https://github.com/rails/solid_cache) - DB-backed caching (Rails 8+)
701
+ - [SolidCable](https://github.com/rails/solid_cable) - DB-backed Action Cable (Rails 8+)
702
+ - [Mission Control - Jobs](https://github.com/rails/mission_control-jobs) - Web dashboard for monitoring jobs
703
+
704
+ </resources>