askill
vanilla-rails-controllers

vanilla-rails-controllersSafety 90Repository

Use when writing Rails controllers or implementing state changes - enforces resource extraction, thin controllers delegating to models, params.expect, and controller concerns for scoping

2 stars
1.2k downloads
Updated 2/14/2026

Package Files

Loading files...
SKILL.md

Vanilla Rails Controllers

State changes are resources. Every state change becomes its own resource controller with CRUD operations.

Resource Extraction

# Bad - custom actions
resources :cards do
  post :close
  post :archive
end

# Good - state as resource
resources :cards do
  resource :closure, only: [:create, :destroy]
  resource :archival, only: [:create, :destroy]
end

See vanilla-rails-routing for route structure, nesting, and directory mapping.

Common State Resources

State ChangeResourcecreate =destroy =
Close/Reopenclosureclosereopen
Archive/Unarchivearchivalarchiveunarchive
Pin/Unpinpinpinunpin
Publish/Unpublishpublicationpublishunpublish
Assign/Unassignassignmentassignunassign
Follow/Unfollowsubscriptionsubscribeunsubscribe

Thin Controllers, Rich Models

Controllers delegate to intention-revealing model methods. No business logic in controllers.

# Bad - logic in controller
class Cards::ArchivalsController < ApplicationController
  def create
    @card.update(archived: true)
  end
end

# Good - delegate to model
class Cards::ArchivalsController < ApplicationController
  include CardScoped

  def create
    @card.archive
    respond_to do |format|
      format.turbo_stream
      format.json { head :no_content }
    end
  end

  def destroy
    @card.unarchive
    respond_to do |format|
      format.turbo_stream
      format.json { head :no_content }
    end
  end
end

Controller Concerns (Scoping)

Extract parent-finding into concerns. Name describes what's scoped:

# app/controllers/concerns/card_scoped.rb
module CardScoped
  extend ActiveSupport::Concern

  included do
    before_action :set_card
  end

  private
    def set_card
      @card = Card.find(params[:card_id])
    end
end

# app/controllers/concerns/board_scoped.rb
module BoardScoped
  extend ActiveSupport::Concern

  included do
    before_action :set_board
  end

  private
    def set_board
      @board = Current.account.boards.find(params[:board_id])
    end
end

Common concerns:

ConcernSetsUsed by
BoardScoped@boardAll controllers under boards/
CardScoped@cardAll controllers under cards/
Authenticatedsession checkAll controllers needing auth

params.expect()

Use params.expect() instead of params.require().permit():

# Bad
def card_params
  params.require(:card).permit(:title, :description)
end

# Good
def card_params
  params.expect(card: [:title, :description])
end

Migration Pattern

State resources need a table tracking who/when:

create_table :closures, id: :uuid do |t|
  t.uuid :card_id, null: false
  t.uuid :user_id
  t.timestamps
end
add_index :closures, :card_id, unique: true

Red Flags

Red flagFix
post :close, patch :activateExtract resource
Business logic in controllerMove to model
params.require().permit()Use params.expect()
before_action duplicated across controllersExtract scoping concern
Controller > 30 lines per actionDelegate more to model

Self-Check

  • State changes modeled as resources (create/destroy)
  • Controller actions delegate to model methods
  • Parent-finding extracted to scoping concerns
  • params.expect() for strong parameters

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

78/100Analyzed 2 weeks ago

Well-structured Rails controller skill with clear code examples and actionable patterns. Covers resource extraction, thin controllers, concerns, and params.expect. Has when-to-use in description, structured examples, and self-check list. Path suggests internal project folder but patterns are broadly applicable to Rails development. Slight penalty for project-specific routing reference but core content is high-quality and reusable."

90
85
65
70
80

Metadata

Licenseunknown
Version-
Updated2/14/2026
PublisherZempTime

Tags

security