rails-patterns
Lets your agent develop applications with Ruby on Rails. It applies recommended patterns for efficient and maintainable controllers, models, and views.
What it does
This guide teaches how to organize your code in Ruby on Rails applications, following community best practices. It helps keep your project tidy and easy to understand, even as it grows.
When to use it
- ✓When starting a new Rails project.
- ✓When a file in your project becomes too large.
- ✓When reviewing someone else's code.
Example of what to ask your AI
“How do I organize the code to create a new invoice?”
Want more? Open the sections below.
How to use
The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.
Skill link
Ready-to-paste message
How it works
It suggests where to place each type of code (like controllers, services, models) into specific folders. For complex tasks, it recommends using service or form objects instead of putting everything in the controller.
Installation
Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.
In the terminal (Claude Code, Codex, Cursor), in your project folder:
npx skills add affaan-m/ECC --skill rails-patternsOr download just the file:
curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/rails-patterns/SKILL.md -o SKILL.mdTechnical content (original SKILL.md)
Original text by the author, straight from GitHub.
Rails Patterns
Framework patterns for modern Ruby on Rails applications (Rails 7.1+ and 8.x). Rails is opinionated by design; these are the patterns the community has converged on for apps that stay maintainable past the 50-model mark. This skill is the "how." For the "what" and "when" (the decisions about which pattern to reach for), see the Ruby patterns rules — rules/ruby/patterns.md in this repository, installed as rules/ecc/ruby/patterns.md.
When to Activate
- Building a Rails application (full-stack, API-only, or hybrid)
- Reviewing a PR that touches
app/orconfig/ - Generating models, controllers, services, or jobs
- A controller action grows past ~10 lines
- A model file grows past ~200 lines
- ActiveRecord queries start appearing in controllers or views
Core Concepts
The directory contract
Rails apps follow a predictable structure. Add directories deliberately, not casually.
app/
models/ ActiveRecord models. Persistence and domain logic close to the data.
controllers/ HTTP request handling. Thin orchestration only.
views/ ERB templates. No business logic.
components/ ViewComponent classes. View logic that needs tests.
services/ Service objects. Multi-step business operations.
forms/ Form objects. Complex form handling across multiple models.
queries/ Query objects. Reusable, composable ActiveRecord queries.
jobs/ Background jobs. Async work via Solid Queue, Sidekiq, or GoodJob.
mailers/ ActionMailer classes.
helpers/ View helpers. Tiny presentational logic only.
policies/ Authorization policies (if using Pundit). Optional.
channels/ ActionCable channels for WebSocket work.
Avoid app/lib/, app/utils/, app/managers/. If something does not fit the directories above, the design usually needs rethinking, not a new directory. Truly generic code goes in lib/.
Skinny controllers
Controllers receive a request, delegate to the right object, and render a response. Business logic lives elsewhere. (Per the Ruby patterns rules, extract to a service object when the controller starts carrying multiple responsibilities.)
Service objects
The default for business operations that touch more than a single model save. Conventions that keep them consistent:
- Namespace by domain (
Invoices::Create), not by suffix (InvoiceCreator). - A class method
.calldelegates to an instance#call. - Return a Result object, not a boolean or a bare record, so the caller can branch on success, errors, and the affected record.
- Wrap multi-record writes in a transaction.
- Keep each service single-purpose (
Invoices::Create,Invoices::MarkPaid), neverInvoices::Manager.
Form objects
When a form spans multiple models or has fields that do not map to columns, use a form object rather than nested attributes or virtual attributes on the wrong model. It quacks like a model to the view (form_with model: @form) while composing records cleanly.
Query objects
For ActiveRecord queries reused across controllers or services, or too complex for a scope, extract a query object that accepts a scope as input so it composes. Rule of thumb: a scope that grows past three chained conditions or starts taking parameters wants to be a query object.
Background jobs
Offload anything slow. (Per the Ruby patterns rules, Solid Queue for greenfield Rails 8 with modest throughput; Sidekiq when you need mature observability, high throughput, or existing Redis.) Regardless of adapter: pass IDs not records, make perform idempotent, and set retry_on/discard_on explicitly.
ViewComponent over partials
For view logic with conditional rendering, more than two arguments, or reuse across more than three places, prefer a ViewComponent. Components are testable in isolation and surface their interface explicitly; partials with deep conditional logic become debt.
Hotwire: Turbo and Stimulus
The default Rails frontend stack. (Per the Ruby patterns rules, prefer Hotwire for server-rendered apps; reach for React/Vue only when interaction complexity justifies the client surface.) Turbo Frames for partial page updates, Turbo Streams for server-driven updates, Stimulus for small client-side behaviors next to the markup.
The Rails 8 Solid stack
…
FAQ
What are 'skinny controllers'?
It means controllers (which handle web requests) should be short and only orchestrate work, delegating complex logic to other parts of the code, like service objects.
What are 'service objects'?
These are pieces of code that perform a specific, well-defined task, like creating an invoice. They help keep controllers clean and the code more organized.
Why use 'ViewComponent' over 'partials'?
ViewComponents are easier to test and organize complex view logic, making the code more robust and maintainable than traditional 'partials'.
Details
Original description by the author
Ruby on Rails framework patterns for Rails 7.1+ and 8.x apps. Covers the directory contract, skinny controllers with service objects, form objects, query objects, idiomatic ActiveRecord, background jobs, ViewComponent, Hotwire, and the Rails 8 Solid stack. Use when building or reviewing Rails apps, controllers, models, services, jobs, or views.
repo: affaan-m/ECC
Popularity
- GitHub stars
- 280k
- Ranking position
- #110
- License
- MIT
- Updated
- 10/15/2026
Comments
- …
More skills from this repository
accessibility
Helps your agent create interfaces that everyone can use. Ensures websites and apps work well for people with disabilities, like those who are blind or have reduced mobility.
affaan-m/ECC
agent-architecture-audit
Makes your agent check if everything is working correctly. It finds and fixes problems in AI systems, ensuring they perform as expected.
affaan-m/ECC
agent-eval
Helps your agent compare different AI coding tools. It measures which one is faster, cheaper, and more reliable for specific tasks.
affaan-m/ECC
agent-harness-construction
Makes your agent better understand how to perform tasks. It optimizes the tools and instructions the agent uses to increase its chances of success.
affaan-m/ECC
Similar skills
api-and-interface-design
Helps create well-defined APIs and interfaces. It's useful when designing how different parts of software will communicate.
addyosmani/agent-skills
mason
Helps your agent write clean and functional code. It follows defined rules to ensure everything works as expected.
sickn33/agentic-awesome-skills
max
Lets your agent improve existing code without changing what it does. It makes the code easier to read and maintain.
sickn33/agentic-awesome-skills