Claude Skills Guide

Claude Code ActiveRecord Scopes and Callbacks Best Practices

ActiveRecord scopes and callbacks are fundamental building blocks in Rails applications. When used correctly with Claude Code, they enable you to create clean, maintainable, and efficient data layer code. This guide covers best practices for writing scopes and callbacks that work seamlessly with Claude Code’s AI-assisted development workflow.

Understanding ActiveRecord Scopes

Scopes in ActiveRecord allow you to define commonly used queries that can be chained together. They provide a way to encapsulate reusable query logic directly in your models, making your code more expressive and DRY.

Writing Efficient Scopes

When working with Claude Code, you can leverage its AI capabilities to generate optimized scopes. Here’s what makes a scope efficient:

class User < ApplicationRecord
  # Good: Returns an ActiveRecord::Relation
  scope :active, -> { where(active: true) }
  scope :recent, -> { order(created_at: :desc) }
  scope :by_role, ->(role) { where(role: role) if role.present? }
  
  # Chaining works seamlessly
  def self.active_recent
    active.recent
  end
end

Avoiding Common Scope Pitfalls

Claude Code can help you identify and fix common scope issues. Here are the most frequent problems:

  1. Returning nil instead of a relation - This breaks chaining
  2. Using class methods instead of scopes - Scopes are more declarative
  3. Overly complex lambda bodies - Keep scopes focused and simple
# Bad: Returns nil when condition fails
scope :by_status, ->(status) { where(status: status) if status }

# Good: Always returns a relation
scope :by_status, ->(status) { where(status: status) if status.present? }
# Or using `or` with a none relation
scope :by_status, ->(status) { status.present? ? where(status: status) : all }

Mastering ActiveRecord Callbacks

Callbacks allow you to trigger logic before or after changes to an object’s state. They’re essential for automating repetitive tasks like validation, logging, and data synchronization.

Callback Execution Order

Understanding the callback order is crucial for avoiding unexpected behavior:

before_validation
after_validation
before_save
around_save
before_create (for new records)
around_create
after_create
after_save
after_commit
class Order < ApplicationRecord
  before_validation :normalize_email
  before_save :calculate_total
  after_create :send_confirmation_email
  after_commit :notify_inventory_system, on: :create

  private

  def normalize_email
    self.email = email.downcase.strip if email.present?
  end

  def calculate_total
    self.total = line_items.sum(&:price)
  end

  def send_confirmation_email
    OrderMailer.confirmation(self).deliver_later
  end
end

Best Practices for Callbacks

Working with Claude Code, follow these callback best practices:

  1. Keep callbacks focused - Each callback should do one thing
  2. Use before callbacks for validation - Validate before expensive operations
  3. Prefer after_commit for external operations - Avoid side effects that might roll back
class Transaction < ApplicationRecord
  # Good: Single responsibility
  before_create :set_initial_status
  after_commit :sync_to_external_api, on: :create
  after_commit :log_state_change, on: :update

  private

  def set_initial_status
    self.status = :pending
  end

  def sync_to_external_api
    ExternalApi.sync(self)
  end
end

Scopes and Callbacks with Claude Code

Claude Code can help you write, review, and refactor scopes and callbacks. Here’s how to collaborate effectively:

Generating Scopes

Ask Claude Code to generate scopes based on your requirements:

# Prompt: "Create scopes for a User model with roles: admin, editor, viewer
# and include scopes for users created in the last 30 days"

class User < ApplicationRecord
  scope :admins, -> { where(role: 'admin') }
  scope :editors, -> { where(role: 'editor') }
  scope :viewers, -> { where(role: 'viewer') }
  scope :recently_created, -> { where('created_at > ?', 30.days.ago) }
end

Reviewing Callbacks

Use Claude Code to review callback chains for potential issues:

# Before refactoring, ask Claude to analyze:
# - Are there any circular dependencies?
# - Is the callback order correct?
# - Are there any performance concerns?

Advanced Patterns

Custom Scope Methods

Combine scopes with class methods for complex queries:

class Article < ApplicationRecord
  scope :published, -> { where(published: true) }
  scope :featured, -> { where(featured: true) }
  
  def self.with_status(status)
    return published if status == 'published'
    where(status: status)
  end
  
  def self.filter_by_date_range(start_date, end_date)
    where(created_at: start_date..end_date)
  end
end

Conditional Callbacks

Use if and unless to make callbacks conditional:

class Payment < ApplicationRecord
  after_create :send_receipt, if: :amount_exceeds_threshold?
  before_save :encrypt_sensitive_data, if: :sensitive_data_changed?

  private

  def amount_exceeds_threshold?
    amount > 100
  end
end

Testing Scopes and Callbacks

Claude Code can help you write comprehensive tests for scopes and callbacks:

RSpec.describe User do
  describe '.active' do
    let!(:active_user) { create(:user, active: true) }
    let!(:inactive_user) { create(:user, active: false) }

    it 'returns only active users' do
      expect(User.active).to include(active_user)
      expect(User.active).not_to include(inactive_user)
    end
  end

  describe '#send_confirmation_email' do
    let(:user) { build(:user) }

    it 'enqueues confirmation email after create' do
      expect { user.save! }.to have_enqueued_job(ActionMailer::MailDeliveryJob)
    end
  end
end

Conclusion

ActiveRecord scopes and callbacks, when used correctly, make your Rails applications more maintainable and expressive. Claude Code can be an invaluable partner in writing, reviewing, and testing these patterns. Remember to:

With these best practices, you’ll write Rails models that are both powerful and easy to maintain.

Built by theluckystrike — More at zovo.one