
Rails Expert
Give your coding agent vetted Rails Active Record patterns for associations, validations, and query performance while you build the backend.
Overview
Rails Expert is an agent skill for the Build phase that applies Active Record association, validation, and query-optimization patterns for Ruby on Rails backends.
Install
npx skills add https://github.com/jeffallan/claude-skills --skill rails-expertWhat is this skill?
- User, Post, and comment association templates with dependent: :destroy and through: links
- N+1 prevention with includes, preload, eager_load, and joins examples
- Validation and before_save callback patterns such as normalize_email
- Published/recent/by_user scopes and tag through-associations
- Query optimization guidance contrasting bad each-loop access vs eager loading
Adoption & trust: 2.8k installs on skills.sh; 9.7k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent-generated Rails code triggers N+1 queries or inconsistent association options that are hard to catch in review.
Who is it for?
Indie builders maintaining a Rails app who want agent output aligned with common association and includes conventions.
Skip if: Non-Rails stacks, greenfield SPAs without Active Record, or teams needing migration-only generators with no model patterns.
When should I use this skill?
When building or refactoring Rails models, associations, scopes, or controller queries that risk N+1 loads.
What do I get? / Deliverables
You get documented model, scope, and eager-loading snippets the agent can mirror so list and show actions stay efficient.
- Association-heavy model examples
- Eager-loading query snippets
- Validation and callback templates
Recommended Skills
Journey fit
Rails model and database access work belongs on the Build shelf because it produces the core server-side data layer before ship-ready APIs. Associations, scopes, and N+1 fixes are canonical backend subphase tasks for Ruby monoliths and JSON APIs.
How it compares
Copy-paste Rails data-layer reference—not a one-shot CRUD scaffold CLI or MCP database server.
Common Questions / FAQ
Who is rails-expert for?
Solo and small-team builders using Ruby on Rails who delegate model and query work to AI coding agents and want stable Active Record idioms.
When should I use rails-expert?
Use it during Build backend work when adding models, scopes, comments/posts relationships, or fixing slow pages suspected of N+1 access.
Is rails-expert safe to install?
It is instructional Ruby snippets without shell or network hooks in the skill body; review the Security Audits panel on this page before trusting any third-party skill package.
SKILL.md
READMESKILL.md - Rails Expert
# Active Record Patterns ## Model Associations ```ruby # app/models/user.rb class User < ApplicationRecord has_many :posts, dependent: :destroy has_many :comments, dependent: :destroy has_many :commented_posts, through: :comments, source: :post has_one :profile, dependent: :destroy has_one_attached :avatar has_many_attached :documents validates :email, presence: true, uniqueness: true validates :username, presence: true, length: { minimum: 3, maximum: 50 } before_save :normalize_email private def normalize_email self.email = email.downcase.strip end end # app/models/post.rb class Post < ApplicationRecord belongs_to :user has_many :comments, dependent: :destroy has_many :taggings, dependent: :destroy has_many :tags, through: :taggings scope :published, -> { where(published: true) } scope :recent, -> { order(created_at: :desc) } scope :by_user, ->(user) { where(user: user) } validates :title, presence: true, length: { maximum: 200 } validates :body, presence: true end ``` ## Query Optimization Prevent N+1 queries: ```ruby # Bad - N+1 query @posts = Post.all @posts.each { |post| puts post.user.name } # Good - eager loading @posts = Post.includes(:user) @posts.each { |post| puts post.user.name } # Multiple associations @posts = Post.includes(:user, :comments, :tags) # Nested associations @posts = Post.includes(comments: :user) # Use joins when you don't need the associated records @posts = Post.joins(:user).where(users: { active: true }) ``` Query scopes: ```ruby class Post < ApplicationRecord scope :published, -> { where(published: true) } scope :recent, ->(limit = 10) { order(created_at: :desc).limit(limit) } scope :by_tag, ->(tag) { joins(:tags).where(tags: { name: tag }) } scope :search, ->(query) { where("title ILIKE ?", "%#{sanitize_sql_like(query)}%") } # Class method for complex logic def self.trending(days = 7) where("created_at > ?", days.days.ago) .joins(:comments) .group(:id) .order("COUNT(comments.id) DESC") end end # Usage Post.published.recent(5) Post.by_tag("rails").search("hotwire") ``` ## Advanced Queries ```ruby # Select specific columns Post.select(:id, :title, :created_at) # Count and group User.joins(:posts).group(:id).count User.joins(:posts).group("users.id").select("users.*, COUNT(posts.id) as posts_count") # Pluck for arrays User.pluck(:email) User.pluck(:id, :email) # Returns array of arrays # Find by SQL Post.find_by_sql("SELECT * FROM posts WHERE title ILIKE '%rails%'") # Exists? Post.where(published: true).exists? # Batch processing User.find_each(batch_size: 1000) do |user| user.process_something end ``` ## Callbacks ```ruby class User < ApplicationRecord before_validation :normalize_email after_validation :log_errors before_create :generate_token after_create :send_welcome_email before_save :update_slug after_save :clear_cache before_destroy :cleanup_associations after_destroy :log_deletion # Avoid callbacks for business logic - use service objects instead private def normalize_email self.email = email.downcase.strip if email.present? end def generate_token self.token = SecureRandom.hex(32) end end ``` ## Validations ```ruby class Article < ApplicationRecord validates :title, presence: true, length: { minimum: 5, maximum: 200 } validates :slug, uniqueness: { case_sensitive: false } validates :published_at, comparison: { greater_than: Time.current }, if: :published? validates :email, format: { with: URI::MailTo::EMAIL_REGEXP } validates :age, numericality: { greater_than_or_equal_to: 18 } validate :validate_future_date private def validate_future_date if published_at.present? && published_at < Time.current errors.add(:published_at, "must be in the future") end end end ``` ## Migrations ```ruby # db/migrate/20231214_create_posts.rb class CreatePosts < ActiveRecord::Migration[7.1] def change create_tabl