Rails Expert
Jeffallan/claude-skills
Builds Rails 7+ apps with Hotwire Turbo Frames and Streams, Active Record tuning, Action Cable, Sidekiq jobs and RSpec specs, with migration and N+1 checks.
Ruby on Rails framework patterns for Rails 7.1+ and 8.x apps.
$ npx skills add affaan-m/ECC --skill rails-patterns -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install affaan-m/ECC rails-patterns --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/rails-patterns .claude/skills/rails-patterns && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .claude/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/affaan-m/ECC/tree/main/skills/rails-patternsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add affaan-m/ECC --skill rails-patterns -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install affaan-m/ECC rails-patterns --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/rails-patterns .agents/skills/rails-patterns && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .agents/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add affaan-m/ECC --skill rails-patterns -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install affaan-m/ECC rails-patterns --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/rails-patterns .cursor/skills/rails-patterns && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .cursor/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/affaan-m/ECC.git --path skills/rails-patterns--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add affaan-m/ECC --skill rails-patterns -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install affaan-m/ECC rails-patterns --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/rails-patterns .gemini/skills/rails-patterns && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .gemini/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install affaan-m/ECC rails-patternsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add affaan-m/ECC --skill rails-patterns -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/rails-patterns .github/skills/rails-patterns && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .github/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add affaan-m/ECC --skill rails-patterns -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install affaan-m/ECC rails-patterns --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/affaan-m/ECC.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/rails-patterns .opencode/skills/rails-patterns && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "rails-patterns" agent skill from https://github.com/affaan-m/ECC/tree/main/skills/rails-patterns into .opencode/skills/rails-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rails-patterns", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
rails-patternsRuby on Rails framework patterns for Rails 7.1+ and 8.x apps.
Rails Patterns is an agent skill from affaan-m/ECC. 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.
Its SKILL.md is about 4.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Backend development, Background jobs and ORMs and data access. It works with Ruby on Rails and Ruby. The repository describes itself as: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond. The licence is MIT.
Read from SKILL.md and the folder at commit ef648e0. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are ruby, erb and javascript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Rails Patterns loads about 4.1k tokens when it runs. Until then it costs about 90 tokens; SKILL.md has 1,069 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from affaan-m/ECC at commit ef648e0, republished under its MIT licence (© affaan-m). 1,069 words, ~4,126 tokens.
.claude/skills/rails-patterns/SKILL.md (or your agent's skills folder).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.
app/ or config/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/.
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.)
The default for business operations that touch more than a single model save. Conventions that keep them consistent:
Invoices::Create), not by suffix (InvoiceCreator)..call delegates to an instance #call.Invoices::Create, Invoices::MarkPaid), never Invoices::Manager.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.
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.
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.
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.
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.
Rails 8 ships database-backed defaults that previously needed Redis: Solid Queue (jobs), Solid Cache (cache), Solid Cable (ActionCable). The tradeoff is more database load for one fewer infrastructure component; a good fit for modest throughput, with Redis still winning at high scale. Kamal is the default Docker-based deploy tool.
# Bad: business logic in the controller
class InvoicesController < ApplicationController
def create
@invoice = Invoice.new(invoice_params)
@invoice.user = current_user
@invoice.line_items.build(invoice_params[:line_items])
@invoice.tax_total = TaxCalculator.new(@invoice).calculate
@invoice.total = @invoice.line_items.sum(&:amount) + @invoice.tax_total
if @invoice.save
InvoiceMailer.created(@invoice).deliver_later
AccountingExportJob.perform_later(@invoice.id)
redirect_to @invoice, notice: "Invoice created"
else
render :new
end
end
end
# Good: controller orchestrates, service does the work
class InvoicesController < ApplicationController
def create
result = Invoices::Create.call(params: invoice_params, user: current_user)
if result.success?
redirect_to result.invoice, notice: "Invoice created"
else
@invoice = result.invoice
render :new, status: :unprocessable_entity
end
end
end# app/services/invoices/create.rb
module Invoices
class Create
# Struct keeps this runnable on every Ruby that Rails 7.1 supports.
# On Ruby 3.2+, `Data.define(:success?, :invoice, :errors)` is a more
# concise immutable alternative.
Result = Struct.new(:success, :invoice, :errors, keyword_init: true) do
def success?
success
end
end
def self.call(params:, user:)
new(params: params, user: user).call
end
def initialize(params:, user:)
@params = params
@user = user
end
def call
invoice = build_invoice
ApplicationRecord.transaction do
invoice.save!
end
begin
send_notifications(invoice)
rescue StandardError => e
Rails.logger.error("Notification dispatch failed for invoice #{invoice.id}: #{e.message}")
end
Result.new(success: true, invoice: invoice, errors: nil)
rescue ActiveRecord::RecordInvalid => e
Result.new(success: false, invoice: e.record, errors: e.record.errors)
end
private
attr_reader :params, :user
def build_invoice
invoice = user.invoices.new(params.except(:line_items))
invoice.line_items.build(params[:line_items])
invoice.tax_total = TaxCalculator.call(invoice)
invoice.total = invoice.line_items.sum(&:amount) + invoice.tax_total
invoice
end
def send_notifications(invoice)
InvoiceMailer.created(invoice).deliver_later
AccountingExportJob.perform_later(invoice.id)
end
end
end# app/forms/signup_form.rb
class SignupForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :email, :string
attribute :password, :string
attribute :company_name, :string
attribute :terms_accepted, :boolean
validates :email, presence: true, format: URI::MailTo::EMAIL_REGEXP
validates :password, presence: true, length: { minimum: 12 }
validates :company_name, presence: true
validates :terms_accepted, acceptance: true
attr_reader :user, :company
def save
return false unless valid?
ApplicationRecord.transaction do
@company = Company.create!(name: company_name)
@user = @company.users.create!(email: email, password: password, role: :owner)
end
true
rescue ActiveRecord::RecordInvalid => e
errors.merge!(e.record.errors)
false
end
end# app/queries/invoices/overdue.rb
module Invoices
class Overdue
def self.call(scope: Invoice.all, as_of: Time.current)
new(scope: scope, as_of: as_of).call
end
def initialize(scope:, as_of:)
@scope = scope
@as_of = as_of
end
def call
scope
.where(status: :sent)
.where(due_date: ..as_of)
.where.not(id: paid_invoice_ids)
.includes(:customer, :line_items)
end
private
attr_reader :scope, :as_of
def paid_invoice_ids
Payment.where(created_at: ..as_of).pluck(:invoice_id)
end
end
endQuery objects accept a scope, so they compose: Invoices::Overdue.call(scope: current_user.invoices).
# Bad: N+1 in the view when it calls post.author.name
@posts = Post.published
# Good: eager load
@posts = Post.published.includes(:author)includes lets Rails choose preload vs eager_load. Force preload for separate queries, eager_load for a JOIN when filtering on the association. Since Rails 6.1, strict_loading raises on accidental lazy loads.
class Comment < ApplicationRecord
belongs_to :post, counter_cache: true
endadd_column :posts, :comments_count, :integer, default: 0, null: falsepost.comments_count becomes a column read instead of a COUNT(*). This example
assumes a new table; adding a counter cache to a table that already has rows requires a
backfill, which is out of scope here.
Pass record IDs, not records. Retries make delivery at-least-once, so any job that calls an external service must be idempotent — otherwise a transient failure after the remote call succeeds will duplicate the effect on the next attempt.
class AccountingExportJob < ApplicationJob
queue_as :exports
retry_on AccountingApi::TransientError, wait: :polynomially_longer, attempts: 5
discard_on AccountingApi::PermanentError
def perform(invoice_id)
invoice = Invoice.find(invoice_id)
export = AccountingExport.create_or_find_by!(
invoice: invoice,
idempotency_key: "invoice-export-#{invoice.id}-#{invoice.updated_at.to_i}"
)
return if export.completed_at?
receipt = AccountingApi.export(invoice, idempotency_key: export.idempotency_key)
export.update!(completed_at: Time.current, external_id: receipt.id)
end
endadd_index :accounting_exports, :idempotency_key, unique: trueThe unique index is what makes this safe: when two attempts race, the database rejects
the second insert and Active Record resolves the conflict inside the call, returning the
existing row. That happens without any job-level retry — retry_on above covers only
AccountingApi::TransientError. The guard
covers the window before the remote call; passing idempotency_key through to the API
covers the window after it, so a crash between the API call and update! still resolves
to a single export.
# app/components/invoice_status_badge_component.rb
class InvoiceStatusBadgeComponent < ViewComponent::Base
STATUS_CLASSES = {
draft: "bg-gray-100 text-gray-800",
sent: "bg-blue-100 text-blue-800",
paid: "bg-green-100 text-green-800",
overdue: "bg-red-100 text-red-800"
}.freeze
def initialize(invoice:)
@invoice = invoice
end
def call
tag.span(@invoice.status.humanize, class: "rounded-full px-2 py-1 text-sm #{status_class}")
end
private
def status_class
STATUS_CLASSES.fetch(@invoice.status.to_sym, "bg-gray-100")
end
end<%= render InvoiceStatusBadgeComponent.new(invoice: @invoice) %><%# Turbo Frame: clicking Edit replaces only this frame %>
<%= turbo_frame_tag "invoice_#{@invoice.id}" do %>
<div class="invoice">
<%= link_to "Edit", edit_invoice_path(@invoice) %>
</div>
<% end %><%# Turbo Stream: app/views/comments/create.turbo_stream.erb %>
<%= turbo_stream.append "comments", @comment %>
<%= turbo_stream.update "comment_form", partial: "form", locals: { comment: Comment.new } %>// app/javascript/controllers/copy_to_clipboard_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["source"]
copy() {
navigator.clipboard.writeText(this.sourceTarget.value)
}
}# Acceptable: pure data normalization
class User < ApplicationRecord
before_validation :normalize_email
private
def normalize_email
self.email = email.to_s.downcase.strip
end
end
# Move to a service instead: side effects hidden in a callback
# class User < ApplicationRecord
# after_create :send_welcome_email # hard to opt out of, hard to test
# end# Good: genuinely cross-cutting, reusable across unrelated models
# app/models/concerns/soft_deletable.rb
module SoftDeletable
extend ActiveSupport::Concern
included do
scope :active, -> { where(deleted_at: nil) }
scope :deleted, -> { where.not(deleted_at: nil) }
end
def soft_delete! = update!(deleted_at: Time.current)
def restore! = update!(deleted_at: nil)
end
# Bad: a "concern" used by exactly one model, holding logic that belongs on it
# app/models/concerns/invoice_calculations.rb
module InvoiceCalculations
extend ActiveSupport::Concern
def calculate_total
line_items.sum(&:amount) + tax_total
end
end
# Only Invoice includes this. It isn't cross-cutting; it's Invoice's own logic
# hidden in a module for the appearance of a "skinny" model. Put it back on Invoice.A concern used by only one class is just moving code; it belongs in that class. A concern should be reusable across at least two unrelated models.
Any controller past ~80 lines is doing too much. Split actions across controllers or extract to services.
Models should know about their own data. Methods that orchestrate other models, send notifications, or coordinate workflows belong in services.
after_save :update_cache, :send_notifications, :enqueue_export is the start of a debugging nightmare. Move them into a service that runs them explicitly.
accepts_nested_attributes_for is fine for simple cases. For conditional validation or cross-model logic, use a form object.
default_scope { where(deleted: false) } silently excludes records from every query in the app, including the ones you need for support and debugging. Prefer an explicit named scope.
UserRole, OrderStatus, InvoiceState are usually enum candidates, not models.
If the page is server-rendered with occasional interactivity, Hotwire ships faster. Reserve React/Vue for genuinely SPA-shaped apps.
perform idempotent, set retry/discard explicitly.backend-patterns — service boundaries and adapter patterns (referenced by the Ruby patterns rules)rules/ruby/patterns.md, installed as rules/ecc/ruby/patterns.md) — the decisions and when-to-use guidance this skill implements© affaan-m, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/rails-patterns of affaan-m/ECC.
Open the folder on GitHubat commit ef648e0
Rails Patterns next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Rails Patterns this skillaffaan-m/ECC | 276k | — | ~4.1k | Automated safety check: Pass | MIT | |
| Rails ExpertJeffallan/claude-skills | 12k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Ruby Patternssoftspark/ai-toolkit | 179 | — | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| Railsericrisco/rsc-harness | 174 | — | ~3.1k | Automated safety check: Pass | MIT | |
| Ruby Rulessoftspark/ai-toolkit | 179 | — | ~3.4k | Automated safety check: Pass | Apache-2.0 | |
| Rails Idiomsirahardianto/awesome-agv | 157 | — | ~1.8k | Automated safety check: Pass | MIT |
Jeffallan/claude-skills
Builds Rails 7+ apps with Hotwire Turbo Frames and Streams, Active Record tuning, Action Cable, Sidekiq jobs and RSpec specs, with migration and N+1 checks.
softspark/ai-toolkit
Ruby/Rails: blocks, metaprogramming, ActiveRecord, Sidekiq, RSpec, Sorbet, Hanami.
ericrisco/rsc-harness
A skill your agent uses when building or maintaining a Ruby on Rails app — models, controllers, views, routes and migrations; ActiveRecord associations, scopes and query performance; Hotwire (Turbo…
softspark/ai-toolkit
Ruby coding rules: style, patterns, security, testing. An agent skill from softspark/ai-toolkit.
irahardianto/awesome-agv
Ruby on Rails framework patterns: ActiveRecord scopes, N+1 query prevention, model validations, RESTful routing, and RSpec/Minitest testing.
ericrisco/rsc-harness
A skill your agent uses when writing or refactoring plain Ruby outside Rails — scripts, CLIs, gems, libraries: Enumerable chains and blocks, module mixins and value objects, Bundler/gemspec…
affaan-m/ECC
Audits your installed Claude skills and commands for quality, with a quick mode for recently changed skills and a full mode that evaluates all of them through subagents.
affaan-m/ECC
Ingests, indexes, searches, edits and monitors video, audio and live streams through the VideoDB Python SDK, returning stream links, clips and timestamps.
affaan-m/ECC
Scans installed skills for principles that recur across them and proposes rule-file changes: append, revise, add a section, create a file or leave as covered.
affaan-m/ECC
Builds DRAFT counterparty agreements from one markdown template and a small JSON spec per party, with clauses picked by the party's role.
affaan-m/ECC
Measures whether agents actually follow a skill, rule or agent definition by generating scenarios at three strictness levels and scoring tool-call traces.
affaan-m/ECC
Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents.
Works with
Categories
Ruby on Rails framework patterns for Rails 7.1+ and 8.x apps. Rails Patterns is an agent skill from affaan-m/ECC.x apps.
Rails Patterns fits situations like: reviewing Rails apps; tasks that involve Backend development; tasks that involve Background jobs.
Run `npx skills add affaan-m/ECC --skill rails-patterns -a claude-code`. Or copy the skill folder (skills/rails-patterns in affaan-m/ECC) into .claude/skills/rails-patterns in your project. Claude Code loads it when a task matches its description.
Run `npx skills add affaan-m/ECC --skill rails-patterns -a codex`. Or copy the skill folder (skills/rails-patterns in affaan-m/ECC) into .agents/skills/rails-patterns in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add affaan-m/ECC --skill rails-patterns -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rails-patterns, .gemini/skills/rails-patterns, .github/skills/rails-patterns and .opencode/skills/rails-patterns in your project.
SKILL.md names no scripts, command-line tools or credentials: Rails Patterns is instructions for the agent only. Our summary lists: Docker.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Rails Patterns is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.1k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Rails Patterns: Rails Expert (Jeffallan/claude-skills, 12k stars), Ruby Patterns (softspark/ai-toolkit, 179 stars), Rails (ericrisco/rsc-harness, 174 stars) and Ruby Rules (softspark/ai-toolkit, 179 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
affaan-m (a GitHub user) maintains it in affaan-m/ECC, which has 275,546 GitHub stars. The repository holds 673 skills in this directory. The repository was last updated on October 5, 2026.
Source: affaan-m/ECC on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.