Curated library of 39 AI agent skills for Ruby on Rails development. Organized by category: planning, testing, code-quality, ddd, engines, infrastructure, api, patterns, context, orchestration, and workflows. Includes 5 callable workflow skills (rails-tdd-loop, rails-review-flow, rails-setup-flow, rails-quality-flow, rails-engines-flow) for complete development cycles. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and TDD automation.
95
98%
Does it follow best practices?
Impact
95%
1.20xAverage score across 35 eval scenarios
Passed
No known issues
Complete code examples for Pundit and CanCanCan implementations.
# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy
def update?
user.admin? || record.user_id == user.id
end
def destroy?
user.admin?
end
def create?
user.present?
end
end# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:update, :destroy]
def update
authorize @post
if @post.update(post_params)
redirect_to @post, notice: 'Updated successfully'
else
render :edit, status: :unprocessable_entity
end
end
def destroy
authorize @post
@post.destroy
redirect_to posts_path, notice: 'Deleted successfully'
end
private
def set_post
@post = Post.find(params[:id])
end
end# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.admin?
can :manage, :all
else
can :read, :all
can :update, Post, user_id: user.id
can :destroy, Post, user_id: user.id
can :create, Post
end
end
end# app/controllers/posts_controller.rb
class PostsController < ApplicationController
load_and_authorize_resource
def update
if @post.update(post_params)
redirect_to @post, notice: 'Updated successfully'
else
render :edit, status: :unprocessable_entity
end
end
end# spec/policies/post_policy_spec.rb
require 'rails_helper'
RSpec.describe PostPolicy do
subject { described_class.new(user, post) }
let(:post) { create(:post, user: owner) }
let(:owner) { create(:user) }
context 'as the post owner' do
let(:user) { owner }
it { is_expected.to permit_action(:update) }
it { is_expected.to permit_action(:destroy) }
it { is_expected.to permit_action(:create) }
end
context 'as a different user' do
let(:user) { create(:user) }
it { is_expected.not_to permit_action(:update) }
it { is_expected.not_to permit_action(:destroy) }
it { is_expected.to permit_action(:create) }
end
context 'as an admin' do
let(:user) { create(:user, :admin) }
it { is_expected.to permit_action(:update) }
it { is_expected.to permit_action(:destroy) }
it { is_expected.to permit_action(:create) }
end
context 'as a guest' do
let(:user) { nil }
it { is_expected.not_to permit_action(:update) }
it { is_expected.not_to permit_action(:destroy) }
it { is_expected.not_to permit_action(:create) }
end
end# spec/requests/posts_spec.rb
require 'rails_helper'
RSpec.describe 'PATCH /posts/:id', type: :request do
let(:post) { create(:post, user: owner) }
let(:owner) { create(:user) }
it 'allows the owner to update' do
sign_in owner
patch post_path(post), params: { post: { title: 'New Title' } }
expect(response).to have_http_status(:ok)
expect(post.reload.title).to eq('New Title')
end
it 'denies a guest' do
patch post_path(post), params: { post: { title: 'New Title' } }
expect(response).to have_http_status(:unauthorized)
end
it 'denies a different user' do
sign_in create(:user)
patch post_path(post), params: { post: { title: 'New Title' } }
expect(response).to have_http_status(:forbidden)
end
it 'allows an admin to update any post' do
sign_in create(:user, :admin)
patch post_path(post), params: { post: { title: 'Admin Updated' } }
expect(response).to have_http_status(:ok)
end
end# spec/support/shared_examples/authorization.rb
RSpec.shared_examples 'requires authentication' do |action|
it "requires authentication for #{action}" do
public_send(action)
expect(response).to redirect_to(new_user_session_path)
end
end
RSpec.shared_examples 'requires authorization' do |action, resource_owner_method|
it "requires authorization for #{action}" do
other_user = create(:user)
resource = create(described_class.controller_name.singularize, user: other_user)
sign_in create(:user)
public_send(action, params: { id: resource.id })
expect(response).to have_http_status(:forbidden)
end
end# spec/controllers/posts_controller_spec.rb
require 'rails_helper'
RSpec.describe PostsController do
it_behaves_like 'requires authentication', :get, :index
it_behaves_like 'requires authorization', :patch, :update
enddocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
scenario-27
scenario-28
scenario-29
scenario-30
scenario-31
scenario-32
scenario-33
scenario-34
scenario-35
mcp_server
skills
api
api-rest-collection
rails-graphql-best-practices
code-quality
rails-architecture-review
rails-code-conventions
rails-code-review
rails-review-response
rails-security-review
rails-stack-conventions
assets
snippets
refactor-safely
context
rails-context-engineering
rails-project-onboarding
ddd
ddd-boundaries-review
ddd-rails-modeling
ddd-ubiquitous-language
engines
rails-engine-compatibility
rails-engine-docs
rails-engine-extraction
rails-engine-installers
rails-engine-release
rails-engine-reviewer
rails-engine-testing
infrastructure
rails-api-versioning
rails-background-jobs
rails-database-seeding
rails-frontend-hotwire
rails-migration-safety
rails-performance-optimization
orchestration
rails-skills-orchestrator
patterns
ruby-service-objects
strategy-factory-null-calculator
yard-documentation
planning
create-prd
generate-tasks
ticket-planning
testing
rails-bug-triage
rails-tdd-slices
rspec-best-practices
rspec-service-testing