From rails-specialist
Use when designing model associations, adding validations, writing complex queries, or organizing model code. Also applies when choosing between has_many :through and HABTM, optimizing queries with eager loading, or setting up callbacks and scopes. Covers associations, validations, query optimization, and model organization.
npx claudepluginhub chaserx/cpc --plugin rails-specialistThis skill uses the workspace's default tool permissions.
Guidance for designing and implementing ActiveRecord models with proper associations, validations, queries, and performance optimizations in Rails 7+.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Guidance for designing and implementing ActiveRecord models with proper associations, validations, queries, and performance optimizations in Rails 7+.
ActiveRecord supports several association types. Always specify :dependent on has_many and has_one.
| Association | Use case |
|---|---|
belongs_to | Child side of one-to-many or one-to-one |
has_many | Parent side of one-to-many |
has_one | One-to-one relationship |
has_many :through | Many-to-many with join model (preferred) |
has_and_belongs_to_many | Simple many-to-many without join model attributes |
Polymorphic (as:) | Single association pointing to multiple models |
| Delegated type | Rails 6.1+ alternative to STI |
For full code examples of each type, dependent options, and self-referential/delegated type patterns, consult references/associations.md.
Apply validations to enforce data integrity at the model layer:
validates :email, presence: true, uniqueness: trueformat: { with: /pattern/ }numericality: { greater_than: 0 }length: { minimum: 5, maximum: 200 }if: / unless: with method or lambdavalidate :method_name for complex ruleson: :create or custom contexts like on: :registrationFor detailed examples of each validation type, custom validator classes, and a complete options reference, consult references/validations.md.
Define reusable query fragments as scopes. Scopes always return an ActiveRecord::Relation, making them chainable:
class Post < ApplicationRecord
scope :published, -> { where(published: true) }
scope :recent, -> { order(created_at: :desc) }
scope :by_author, ->(user) { where(user: user) }
end
# Chain scopes together
Post.published.recent.by_author(current_user).limit(10)
Prefer scopes over class methods for simple query conditions.
| Strategy | Loads data? | Filter on assoc? | Best for |
|---|---|---|---|
includes | Yes | Yes (auto-picks) | General-purpose eager load |
preload | Yes | No | Large or multiple assocs |
eager_load | Yes | Yes | Filtering on association |
joins | No | Yes | Filtering without loading |
User.select(:id, :name) or pluck(:email)find_each / in_batches for large datasetsinsert_all / upsert_all for mass writes (skip callbacks)belongs_to :user, counter_cache: true to avoid COUNT queriesUser.where(id: Post.published.select(:user_id))User.where(email: value).exists? (stops at first match)For full code examples of all query patterns, consult references/query-patterns.md.
Use callbacks sparingly — only for model-centric operations:
class User < ApplicationRecord
before_validation :normalize_email
before_save :encrypt_password, if: :password_changed?
after_create :send_welcome_email
after_destroy :cleanup_associated_files
end
Callback order: before_validation → after_validation → before_save → before_create/before_update → after_create/after_update → after_save → after_commit/after_rollback
Avoid callbacks for:
after_commit or a dedicated gem)Organize model code in a consistent order:
class User < ApplicationRecord
# 1. Includes and extends
include Searchable
# 2. Constants
ROLES = %w[admin member guest].freeze
# 3. Associations
has_many :posts, dependent: :destroy
has_one :profile, dependent: :destroy
# 4. Validations
validates :email, presence: true, uniqueness: true
# 5. Scopes
scope :active, -> { where(active: true) }
# 6. Callbacks
before_save :normalize_email
# 7. Class methods
def self.find_by_credentials(email, password)
find_by(email: email)&.authenticate(password)
end
# 8. Instance methods
def full_name
"#{first_name} #{last_name}"
end
# 9. Private methods
private
def normalize_email
self.email = email.downcase.strip
end
end
| Need | Solution |
|---|---|
| Load association data | includes(:association) |
| Filter by association | joins(:association).where(...) |
| Count without query | Counter cache |
| Process large dataset | find_each or in_batches |
| Bulk insert | insert_all |
| Custom validation | validate :method_name |
| Reusable query | scope :name, -> { ... } |
For detailed patterns and code examples, consult:
references/associations.md — Association types, dependent options, polymorphic, delegated typesreferences/validations.md — Validation patterns, custom validators, contexts, options referencereferences/query-patterns.md — N+1 prevention, scopes, batching, bulk operations, counter caches