Agent skill
activerecord
Install this agent skill to your Project
npx add-skill https://github.com/hoblin/claude-code-rails-skills/tree/main/activerecord
SKILL.md
ActiveRecord
This skill provides comprehensive guidance for working with ActiveRecord in Rails applications. Use for writing migrations, defining associations, optimizing queries, preventing N+1 issues, implementing validations, and following database best practices.
Quick Reference
CRUD Operations
# Create
user = User.create(name: "Alice", email: "alice@example.com")
user = User.create!(...) # Raises on failure
# Read
User.find(1) # Raises RecordNotFound
User.find_by(email: "x") # Returns nil if not found
User.where(active: true) # Returns Relation
# Update
user.update(name: "Bob")
user.update!(...) # Raises on failure
# Delete (callbacks run)
user.destroy
# Delete (no callbacks)
user.delete
Key Concepts
| Concept | Purpose |
|---|---|
belongs_to |
Child side of association (has foreign key) |
has_many / has_one |
Parent side of association |
has_many :through |
Many-to-many via join model |
includes / preload |
Eager loading (prevent N+1) |
scope |
Named query builder |
validates |
Model-level data validation |
before_save / after_commit |
Lifecycle callbacks |
Eager Loading Decision Tree
Need to access associated data?
├── NO → Use `joins` (filtering only)
└── YES → Need to filter/sort by association?
├── NO → Use `preload` (separate queries)
└── YES → Large dataset with many associations?
├── YES → Use `includes` with `references`
└── NO → Use `eager_load` (single JOIN)
Quick Comparison
| Method | Strategy | Best For |
|---|---|---|
includes |
Auto-choose | Default choice |
preload |
Separate queries | Large datasets, no filtering |
eager_load |
LEFT OUTER JOIN | Filtering by association |
joins |
INNER JOIN | Filtering only, not accessing data |
# N+1 problem
Post.all.each { |p| p.author.name } # 1 + N queries
# Solution
Post.includes(:author).each { |p| p.author.name } # 2 queries
Validation vs Constraint Decision
Does the rule ALWAYS apply, regardless of business logic?
├── Yes → Database constraint
│ └── Examples: NOT NULL, foreign keys, unique emails
└── No → Model validation
└── Examples: Format rules that change, conditional requirements
Need helpful user-facing error messages?
├── Yes → Model validation (possibly WITH constraint)
└── No → Constraint alone is fine
Best Practice: Use both for critical fields:
# Migration (data integrity)
add_index :users, :email, unique: true
# Model (user feedback)
validates :email, presence: true, uniqueness: true
Associations Quick Reference
Basic Types
class Author < ApplicationRecord
has_many :books, dependent: :destroy
has_one :profile
end
class Book < ApplicationRecord
belongs_to :author # Required by default
belongs_to :publisher, optional: true # Allow NULL
end
Through Associations
class Physician < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
belongs_to :patient
# Join model can have attributes
validates :scheduled_at, presence: true
end
Critical Options
| Option | Purpose |
|---|---|
inverse_of |
Required with custom foreign_key |
dependent: :destroy |
Cascade delete with callbacks |
counter_cache: true |
Cache association count |
touch: true |
Update parent's updated_at |
Migrations Quick Reference
Safe Patterns
# Always reversible
add_column :users, :name, :string
add_index :users, :email, unique: true
add_reference :orders, :user, foreign_key: true
# Concurrent index (no table lock)
disable_ddl_transaction!
add_index :users, :email, algorithm: :concurrently
Must Include Type for Reversibility
remove_column :users, :legacy_field, :string # Include type!
change_column_default :users, :status, from: nil, to: "active"
Callbacks Quick Reference
Order of Execution
before_validation → after_validation →
before_save → around_save → before_create →
around_create → [INSERT] → after_create →
after_save → [COMMIT] → after_commit
Critical Rule: Use after_commit for External Systems
# WRONG - Race condition!
after_save :enqueue_processing
# CORRECT - Runs after COMMIT
after_commit :enqueue_processing, on: :create
Batch Processing
# BAD - loads all records
User.all.each { |u| process(u) }
# GOOD - processes in batches
User.find_each { |u| process(u) }
# Bulk operations
User.where(old: true).in_batches.update_all(archived: true)
Best Practices
Do
- Add database index for columns used in WHERE, ORDER BY, JOIN
- Use
includesto prevent N+1 queries - Pair uniqueness validations with unique database indexes
- Use
find_eachfor processing large datasets - Use
pluck(:column)instead ofall.map(&:column) - Define
inverse_ofwhen using customforeign_key - Use
after_commitfor background jobs and external APIs - Prefer
has_many :throughoverhas_and_belongs_to_many
Don't
- Don't use
default_scope(causes subtle issues) - Don't use
deletewhen you need callbacks - Don't skip database constraints for critical uniqueness
- Don't use
update_columnto bypass validations casually - Don't reference models in migrations (use raw SQL)
- Don't edit already-deployed migrations
- Don't use
after_savefor external system interactions
Anti-Patterns Quick List
| Anti-Pattern | Solution |
|---|---|
| N+1 queries | Use includes, preload, or eager_load |
User.all.map(&:email) |
Use User.pluck(:email) |
| Uniqueness without index | Add unique database index |
validates :active, presence: true |
Use inclusion: { in: [true, false] } for booleans |
after_save for jobs |
Use after_commit |
| Callback hell | Extract to service objects |
default_scope |
Use explicit scopes |
has_and_belongs_to_many |
Use has_many :through |
Additional Resources
Reference Files
For detailed patterns and complete API references, consult:
references/basics.md- Conventions, CRUD, dirty tracking, STI, type castingreferences/migrations.md- Schema changes, indexes, constraints, safe patternsreferences/validations.md- Built-in validators, custom validators, contextsreferences/callbacks.md- Lifecycle hooks, transaction callbacks, alternativesreferences/associations.md- All association types, inverse_of, dependent optionsreferences/querying.md- Finders, eager loading, scopes, batch processing
Example Files
Ready-to-use code patterns in examples/:
examples/basics/- CRUD, dirty tracking, type casting, inheritanceexamples/migrations/- Schema changes, indexes, safe patterns, reversibilityexamples/validations/- Built-in, conditional, custom, contexts, constraintsexamples/callbacks/- Lifecycle, transaction callbacks, conditional, alternativesexamples/associations/- Basic, through, polymorphic, self-referential, extensionsexamples/querying/- Finders, eager loading, scopes, batch processing, optimization
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
Draper Decorators
This skill should be used when the user asks to "create a decorator", "write a decorator", "move logic into decorator", "clean logic out of the view", "isn't it decorator logic", "test a decorator", or mentions Draper, keeping views clean, or representation logic in decorators. Should also be used when editing *_decorator.rb files, working in app/decorators/ directory, questioning where formatting methods belong (models vs decorators vs views), or discussing methods like full_name, formatted_*, display_* that don't belong in models. Provides guidance on Draper gem best practices for Rails applications.
RSpec Testing
This skill should be used when the user asks to "write specs", "create spec", "add RSpec tests", "fix failing spec", or mentions RSpec, describe blocks, it blocks, expect syntax, test doubles, or matchers. Should also be used when editing *_spec.rb files, working in spec/ directory, planning implementation phases that include tests (TDD/RGRC workflow), writing Testing Strategy or Success Criteria sections, discussing unit or integration tests, or reviewing spec output and test failures. Comprehensive RSpec and FactoryBot reference with best practices, ready-to-use patterns, and examples.
MCP Server (Ruby)
This skill should be used when the user asks to "create an MCP server", "build MCP tools", "define MCP prompts", "register MCP resources", "implement Model Context Protocol", or mentions the mcp gem, MCP::Server, MCP::Tool, JSON-RPC transport, stdio transport, or streamable HTTP transport. Should also be used when editing MCP server files, working with tool/prompt/resource definitions, or discussing LLM tool integrations in Ruby.
verl-rl-training
Provides guidance for training LLMs with reinforcement learning using verl (Volcano Engine RL). Use when implementing RLHF, GRPO, PPO, or other RL algorithms for LLM post-training at scale with flexible infrastructure backends.
openrlhf-training
High-performance RLHF framework with Ray+vLLM acceleration. Use for PPO, GRPO, RLOO, DPO training of large models (7B-70B+). Built on Ray, vLLM, ZeRO-3. 2× faster than DeepSpeedChat with distributed architecture and GPU resource sharing.
gguf-quantization
GGUF format and llama.cpp quantization for efficient CPU/GPU inference. Use when deploying models on consumer hardware, Apple Silicon, or when needing flexible quantization from 2-8 bit without GPU requirements.
Didn't find tool you were looking for?