Claude Code Plugins

Community-maintained marketplace

Feedback

Rails Error Prevention

@Kaakati/rails-enterprise-dev
1
0

Comprehensive checklist and prevention strategies for common Ruby on Rails errors. Use this skill BEFORE writing any Rails code to prevent ViewComponent template errors, ActiveRecord query mistakes, method exposure issues, N+1 queries, and other common Rails pitfalls.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name Rails Error Prevention
description Comprehensive checklist and prevention strategies for common Ruby on Rails errors. Use this skill BEFORE writing any Rails code to prevent ViewComponent template errors, ActiveRecord query mistakes, method exposure issues, N+1 queries, and other common Rails pitfalls.

Rails Error Prevention Skill

This skill provides preventative checklists and error patterns for common Rails mistakes. Review relevant sections BEFORE writing code.

When to Use This Skill

  • Before creating ViewComponents
  • Before writing ActiveRecord queries with GROUP BY or joins
  • Before writing view code that calls component methods
  • Before creating controller actions
  • When debugging undefined method errors
  • When debugging template not found errors
  • When debugging ActiveRecord grouping errors

Critical Rule: Method Exposure Verification

This is the #1 cause of runtime errors in Rails applications.

WRONG ASSUMPTION: Service has method → View can call it through component
CORRECT RULE:     Service has method + Component exposes it = View can call it

Verification Process

# Step 1: List all methods view will call on component
grep -oE '@[a-z_]+\.[a-z_]+' app/views/{path}/*.erb | sort -u

# Step 2: List all public methods in component
grep -E '^\s+def [a-z_]+' app/components/{component}_component.rb

# Step 3: Compare - any view call without component method = BUG
# Missing methods MUST be added to component BEFORE writing view code

Patterns to Fix Missing Methods

# Pattern 1: Delegation
class Metrics::DashboardComponent < ViewComponent::Base
  delegate :calculate_lifetime_tasks,
           :calculate_lifetime_success_rate,
           to: :@service
  
  def initialize(service:)
    @service = service
  end
end

# Pattern 2: Wrapper methods (preferred for transformation)
class Metrics::DashboardComponent < ViewComponent::Base
  def initialize(service:)
    @service = service
  end
  
  def lifetime_tasks
    @service.calculate_lifetime_tasks
  end
  
  def lifetime_success_rate
    @service.calculate_lifetime_success_rate
  end
end

# Pattern 3: Expose service directly (use sparingly)
class Metrics::DashboardComponent < ViewComponent::Base
  attr_reader :service
  
  def initialize(service:)
    @service = service
  end
end
# View then calls: dashboard.service.calculate_lifetime_tasks

ViewComponent Errors

Template Not Found

Error Pattern:

Couldn't find a template file or inline render method for {Component}

Root Causes:

  • Missing template file (component.html.erb)
  • Template in wrong location
  • Class name doesn't match file path
  • Using render without inline template defined

Prevention Checklist:

# Before creating component:
ls app/components/                              # Check structure
head -50 app/components/*_component.rb | head -1 # Review existing pattern
# Verify naming: ComponentName -> component_name/

Required Files:

app/components/{namespace}/{component_name}_component.rb
app/components/{namespace}/{component_name}_component.html.erb

Correct Patterns:

# Option A: Separate template file
# app/components/metrics/kpi_card_component.rb
class Metrics::KpiCardComponent < ViewComponent::Base
  def initialize(title:, value:)
    @title = title
    @value = value
  end
end

# app/components/metrics/kpi_card_component.html.erb
# <div class="kpi-card">
#   <h3><%= @title %></h3>
#   <span><%= @value %></span>
# </div>

# Option B: Inline template (call method)
class Metrics::KpiCardComponent < ViewComponent::Base
  def initialize(title:, value:)
    @title = title
    @value = value
  end

  def call
    content_tag :div, class: "kpi-card" do
      safe_join([
        content_tag(:h3, @title),
        content_tag(:span, @value)
      ])
    end
  end
end

Helper Method Errors

Error Pattern:

undefined local variable or method '{method}' for an instance of {Component}
Did you mean `helpers.{method}`?

Root Cause: Calling view helper directly without helpers. prefix

Prevention Rules:

  • ViewComponents do NOT have direct access to view helpers
  • Must use helpers.method_name for any Rails helper

Helpers Requiring Prefix:

# WRONG                          # CORRECT
link_to(...)                     helpers.link_to(...)
image_tag(...)                   helpers.image_tag(...)
url_for(...)                     helpers.url_for(...)
form_with(...)                   helpers.form_with(...)
number_to_currency(...)          helpers.number_to_currency(...)
time_ago_in_words(...)           helpers.time_ago_in_words(...)
truncate(...)                    helpers.truncate(...)
pluralize(...)                   helpers.pluralize(...)
content_tag(...)                 helpers.content_tag(...)
tag(...)                         helpers.tag(...)
content_for(...)                 helpers.content_for(...)

Alternative - Delegate Helpers:

class Metrics::KpiCardComponent < ViewComponent::Base
  delegate :number_to_currency, :link_to, to: :helpers

  def formatted_value
    number_to_currency(@value)  # Now works without prefix
  end
end

Content Block Errors

Error Pattern:

content is not defined

Prevention: Always check content? before using content

<% if content? %>
  <%= content %>
<% end %>

ActiveRecord Errors

Grouping Error (PostgreSQL)

Error Pattern:

PG::GroupingError: ERROR: column "{table}.{column}" must appear in the GROUP BY clause

Root Causes:

  • SELECT includes columns not in GROUP BY or aggregate functions
  • Using .select with .group but including non-grouped columns
  • Eager loading (includes/preload) with GROUP BY
  • Using .pluck or .select with associations and GROUP BY

Prevention Rules:

  1. Every non-aggregated column in SELECT must be in GROUP BY
  2. NEVER combine includes/preload/eager_load with GROUP BY
  3. Use .select only for grouped columns and aggregates
  4. If you need associated data with grouped results, query separately

Examples:

# WRONG - selecting all columns with group
Task.includes(:user).group(:task_type).count
# This tries to select tasks.* which fails

# WRONG - selecting id with group
Task.select(:task_type, :id).group(:task_type).count
# id is not grouped or aggregated

# CORRECT - only select grouped columns and aggregates
Task.group(:task_type).count
# => { "type_a" => 5, "type_b" => 3 }

# CORRECT - explicit select with only valid columns
Task.select(:task_type, 'COUNT(*) as count').group(:task_type)

# CORRECT - if you need associated data, query separately
type_counts = Task.group(:task_type).count
tasks_by_type = type_counts.keys.each_with_object({}) do |type, hash|
  hash[type] = Task.where(task_type: type).includes(:user).limit(5)
end

# CORRECT - using pluck for simple aggregations
Task.group(:task_type).pluck(:task_type, 'COUNT(*)')
# => [["type_a", 5], ["type_b", 3]]

Before Writing GROUP BY Query:

# Detection command
grep -r '\.group(' app/ --include='*.rb' -A3 -B3
grep -r '\.includes.*\.group\|.group.*\.includes' app/ --include='*.rb'

N+1 Queries

Detection: Multiple queries for same association in logs

Prevention:

# WRONG - N+1
tasks.each { |t| puts t.user.name }

# CORRECT
tasks.includes(:user).each { |t| puts t.user.name }

Ambiguous Column

Error Pattern:

PG::AmbiguousColumn: ERROR: column reference "{column}" is ambiguous

Prevention: Always qualify columns when joining

# WRONG
User.joins(:tasks).where(status: 'active')  # Both have status?

# CORRECT
User.joins(:tasks).where(users: { status: 'active' })
# OR
User.joins(:tasks).where('users.status = ?', 'active')

Missing Attribute

Error Pattern:

ActiveModel::MissingAttributeError: missing attribute: {attribute}

Prevention: Include all attributes needed downstream

# WRONG - later code needs 'email'
users = User.select(:id, :name)
users.each { |u| puts u.email }  # ERROR!

# CORRECT
users = User.select(:id, :name, :email)

Controller Errors

Missing Template

Error Pattern:

ActionView::MissingTemplate

Prevention:

  • Every non-redirect action needs a view OR explicit render
  • View path must match controller namespace
# Before creating controller action:
ls app/views/{controller}/

Unknown Action

Error Pattern:

AbstractController::ActionNotFound

Root Causes:

  • Route points to non-existent action
  • Action is private/protected (must be public)
# Verification
rails routes | grep {controller}
grep -n 'def ' app/controllers/{controller}_controller.rb

Nil Errors

Error Pattern:

undefined method '{method}' for nil:NilClass

Prevention Patterns:

# Safe navigation
user&.profile&.settings&.theme

# Guard clause
return unless user&.profile

# With default
user&.profile&.settings&.theme || 'default'

# Early return
def process_user(user)
  return if user.nil?
  # ... rest of method
end

Argument Errors

Error Pattern:

ArgumentError: wrong number of arguments (given X, expected Y)

Prevention:

# Before modifying method signature
grep -r 'method_name' app/ --include='*.rb'
# Update all call sites

Rules:

  • Prefer keyword arguments for methods with 2+ params
  • Use default values for optional params

Prevention Checklists

Before Creating ViewComponent

[ ] Check app/components/ structure
[ ] Review existing component for template pattern (inline vs file)
[ ] Verify naming: Namespace::ComponentNameComponent
[ ] Create both .rb AND .html.erb files (unless using inline)
[ ] List ALL methods view will need
[ ] Implement ALL needed methods in component
[ ] Prefix ALL Rails helpers with 'helpers.' or delegate them

Before Writing View Code

[ ] List ALL methods view will call on component
[ ] For EACH method, verify it exists in component class
[ ] If method missing, ADD to component BEFORE view code
[ ] Verify underlying service/model has implementation

Before Writing ActiveRecord Query with GROUP BY

[ ] List ALL columns in SELECT
[ ] Verify each is in GROUP BY or aggregate function
[ ] Remove includes/preload/eager_load
[ ] Test query in rails console first

Before Writing ActiveRecord Query with Joins

[ ] Qualify ambiguous columns with table name
[ ] Consider if includes is better for the use case

Before Creating Controller Action

[ ] View exists for non-redirect actions?
[ ] Routes point to public methods?
[ ] All @variables view needs are set?

Before Any Code

[ ] Inspect existing similar implementations
[ ] Check naming conventions in codebase
[ ] Verify all dependencies exist (gems, files, routes)
[ ] Verify method exposure across all layers (view→component→service)

Quick Debugging Commands

# Find where method is called
grep -r 'method_name' app/ --include='*.rb'

# Find method definition
grep -rn 'def method_name' app/ --include='*.rb'

# Check method visibility
grep -B5 'def method_name' app/path/to/file.rb

# List component methods
grep -E '^\s+def [a-z_]+' app/components/path_component.rb

# List service methods  
grep -E '^\s+def [a-z_]+' app/services/path.rb

# Compare view calls vs component methods
grep -oE '@\w+\.\w+' app/views/path/*.erb | sort -u