rails generate model User name:string email:string, rails generate controller Users
rails db:migrate and verify schema with rails db:schema:dump
db/schema.rb for conflicts, rollback with rails db:rollback, fix and retrybundle exec rspec must pass; bundle exec rubocop for style
--format documentation for detailincludes/eager_load (see Common Patterns) and re-run specsLoad detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Hotwire/Turbo | references/hotwire-turbo.md |
Turbo Frames, Streams, Stimulus controllers |
| Active Record | references/active-record.md |
Models, associations, queries, performance |
| Background Jobs | references/background-jobs.md |
Sidekiq, job design, queues, error handling |
| Testing | references/rspec-testing.md |
Model/request/system specs, factories |
| API Development | references/api-development.md |
API-only mode, serialization, authentication |
# BAD — triggers N+1
posts = Post.all
posts.each { |post| puts post.author.name }
# GOOD — eager load association
posts = Post.includes(:author).all
posts.each { |post| puts post.author.name }
# GOOD — eager_load forces a JOIN (useful when filtering on association)
posts = Post.eager_load(:author).where(authors: { verified: true })
<%# app/views/posts/index.html.erb %>
<%= turbo_frame_tag "posts" do %>
<%= render @posts %>
<%= link_to "Load More", posts_path(page: @next_page) %>
<% end %>
<%# app/views/posts/_post.html.erb %>
<%= turbo_frame_tag dom_id(post) do %>
<h2><%= post.title %></h2>
<%= link_to "Edit", edit_post_path(post) %>
<% end %>
# app/controllers/posts_controller.rb
def index
@posts = Post.includes(:author).page(params[:page])
@next_page = @posts.next_page
end
# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
queue_as :default
sidekiq_options retry: 3, dead: false
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
rescue ActiveRecord::RecordNotFound => e
Rails.logger.warn("SendWelcomeEmailJob: user #{user_id} not found — #{e.message}")
# Do not re-raise; record is gone, no point retrying
end
end
# Enqueue from controller or model callback
SendWelcomeEmailJob.perform_later(user.id)
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: %i[show edit update destroy]
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post, notice: "Post created."
else
render :new, status: :unprocessable_entity
end
end
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body, :published_at)
end
end
includes/eager_load on every collection query involving associationsWHERE, ORDER BY, or JOIN
sanitize_sql or parameterized queries only)When implementing Rails features, provide: