This skill should be used when the user asks about controllers, routing, request handling, RESTful design, controller concerns, strong parameters, filters, or API endpoints. Trigger phrases include "controller", "routing", "routes", "RESTful", "slim controllers", "before_action", "params", "strong parameters", "respond_to", "API design", "concerns".
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/concerns.rbexamples/restful-controller.rbreferences/api-controllers.mdreferences/routing-patterns.mdExpertise in routing, RESTful design, slim controllers, concerns, and request handling for Rails 8 applications.
Controllers are traffic cops. They receive requests, coordinate with models, and render responses. That's it. If your controller action has more than 5-7 lines, something's wrong.
Every resource controller should have at most seven actions:
| Action | HTTP | Path | Purpose |
|---|---|---|---|
| index | GET | /articles | List all |
| show | GET | /articles/:id | Show one |
| new | GET | /articles/new | Form for create |
| create | POST | /articles | Create record |
| edit | GET | /articles/:id/edit | Form for update |
| update | PATCH/PUT | /articles/:id | Update record |
| destroy | DELETE | /articles/:id | Delete record |
If you need more actions, you need more controllers.
bin/rails generate controller Articles index show new create edit update destroy
Or for a complete resource:
bin/rails generate scaffold Article title:string body:text user:references
# config/routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments, only: [:create, :destroy]
member do
post :publish
end
collection do
get :drafts
end
end
end
Avoid deep nesting. Use shallow:
resources :articles, shallow: true do
resources :comments
end
# Generates:
# GET /articles/:article_id/comments (index)
# POST /articles/:article_id/comments (create)
# GET /comments/:id (show)
# DELETE /comments/:id (destroy)
# Namespace: adds module and URL prefix
namespace :admin do
resources :articles # Admin::ArticlesController, /admin/articles
end
# Scope: URL prefix only
scope :admin do
resources :articles # ArticlesController, /admin/articles
end
# Module: module only
scope module: :admin do
resources :articles # Admin::ArticlesController, /articles
end
class ArticlesController < ApplicationController
def create
@article = current_user.articles.build(article_params)
if @article.save
redirect_to @article, notice: "Article created."
else
render :new, status: :unprocessable_entity
end
end
end
That's it. No business logic. The model handles validation and persistence.
Extract common setup:
class ArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
before_action :require_author, only: [:edit, :update, :destroy]
private
def set_article
@article = Article.find(params[:id])
end
def require_author
redirect_to articles_path unless @article.user == current_user
end
end
class ArticlesController < ApplicationController
private
def article_params
params.require(:article).permit(:title, :body, :published_at)
end
end
def article_params
params.require(:article).permit(
:title,
:body,
comments_attributes: [:id, :content, :_destroy],
tag_ids: []
)
end
def article_params
permitted = [:title, :body]
permitted << :published_at if current_user.admin?
params.require(:article).permit(permitted)
end
Extract shared behavior across controllers:
# app/controllers/concerns/authenticatable.rb
module Authenticatable
extend ActiveSupport::Concern
included do
before_action :authenticate_user!
helper_method :current_user
end
private
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
def authenticate_user!
redirect_to login_path unless current_user
end
end
# Usage in controller
class ArticlesController < ApplicationController
include Authenticatable
end
def update
if @article.update(article_params)
redirect_to @article, notice: "Updated successfully."
else
render :edit, status: :unprocessable_entity
end
end
class Api::ArticlesController < ApplicationController
def index
@articles = Article.published.includes(:user)
render json: @articles
end
def create
@article = current_user.articles.build(article_params)
if @article.save
render json: @article, status: :created
else
render json: { errors: @article.errors }, status: :unprocessable_entity
end
end
end
def create
@article = current_user.articles.build(article_params)
respond_to do |format|
if @article.save
format.turbo_stream
format.html { redirect_to @article }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
bin/rails generate authentication
Creates:
User model with has_secure_passwordSession model for session tokensSessionsController for login/logoutPasswordsController for reset flowAuthentication concern# app/controllers/concerns/authentication.rb
module Authentication
extend ActiveSupport::Concern
included do
before_action :require_authentication
helper_method :authenticated?
end
private
def authenticated?
Current.session.present?
end
def require_authentication
resume_session || request_authentication
end
end
# BAD: Business logic in controller
def create
@order = Order.new(order_params)
@order.total = calculate_total(@order)
@order.apply_discount(current_user.loyalty_level)
@order.tax = @order.total * 0.08
if inventory_sufficient?(@order)
@order.save
send_confirmation_email(@order)
update_inventory(@order)
redirect_to @order
end
end
# GOOD: Model handles business logic
def create
@order = current_user.orders.build(order_params)
if @order.complete!
redirect_to @order, notice: "Order placed."
else
render :new, status: :unprocessable_entity
end
end
DON'T add non-RESTful actions. Create new controllers instead:
# BAD
resources :articles do
post :publish
post :unpublish
post :archive
end
# GOOD
resources :articles
resources :published_articles, only: [:create, :destroy]
resources :archived_articles, only: [:create, :destroy]
references/routing-patterns.md - Advanced routingreferences/api-controllers.md - JSON API patternsexamples/restful-controller.rb - Complete exampleexamples/concerns.rb - Concern patterns