Install
$ agentstack add skill-dallay-agents-skills-rails-development ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
When to Use
- Building or refactoring a Ruby on Rails application.
- Writing ActiveRecord models with validations, associations, and scopes.
- Setting up RESTful routes and controllers following Rails conventions.
- Writing tests with RSpec and FactoryBot.
- Configuring background jobs with Sidekiq or ActiveJob.
- Optimizing database queries to prevent N+1 problems.
Critical Patterns
- Convention Over Configuration: Follow Rails naming conventions strictly. Model
Usermaps to
table users, controller UsersController in users_controller.rb. Fighting conventions creates maintenance nightmares.
- Fat Model, Skinny Controller: Controllers handle HTTP flow only — delegate business logic to
models, service objects, or concerns.
- Prevent N+1 Queries: ALWAYS use
includes,preload, oreager_loadwhen accessing
associations in collections. Use bullet gem in development to detect violations.
- Strong Parameters: NEVER trust user input. Whitelist permitted params in every controller
action.
- Database-Level Constraints: Add validations in the model AND enforce them at the database
level with migration constraints (null: false, unique indexes, foreign keys).
- Background Jobs for Slow Work: Anything over 100ms that isn't the core response (emails, file
processing, API calls) goes into a background job.
Code Examples
Model with Validations and Associations
# app/models/user.rb
class User { where(deactivated_at: nil) }
scope :admins, -> { where(role: "admin") }
scope :created_after, ->(date) { where("created_at > ?", date) }
scope :search, ->(query) {
where("name ILIKE :q OR email ILIKE :q", q: "%#{sanitize_sql_like(query)}%")
}
# Callbacks — use sparingly
before_save :normalize_email
private
def normalize_email
self.email = email.downcase.strip
end
end
Migration with Proper Constraints
class CreateUsers "rails/health#show", as: :rails_health_check
end
Preventing N+1 Queries
# BAD — triggers N+1
users = User.all
users.each { |u| puts u.posts.count }
# GOOD — eager loads associations
users = User.includes(:posts).all
users.each { |u| puts u.posts.size } # .size uses preloaded data
# GOOD — when you only need counts
users = User.left_joins(:posts)
.select("users.*, COUNT(posts.id) AS posts_count")
.group("users.id")
# GOOD — counter cache for frequent counts
# Migration: add_column :users, :posts_count, :integer, default: 0
class Post e
ServiceResult.new(success: false, errors: e.record.errors.full_messages)
end
end
end
RSpec Tests
# spec/models/user_spec.rb
RSpec.describe User, type: :model do
describe "validations" do
subject { build(:user) }
it { is_expected.to validate_presence_of(:email) }
it { is_expected.to validate_uniqueness_of(:email).case_insensitive }
it { is_expected.to validate_presence_of(:name) }
end
describe "associations" do
it { is_expected.to have_many(:posts).dependent(:destroy) }
it { is_expected.to belong_to(:organization).optional }
end
describe ".active" do
it "excludes deactivated users" do
active_user = create(:user, deactivated_at: nil)
create(:user, deactivated_at: 1.day.ago)
expect(User.active).to eq([active_user])
end
end
end
# spec/requests/api/v1/users_spec.rb
RSpec.describe "Api::V1::Users", type: :request do
let(:admin) { create(:user, role: "admin") }
let(:headers) { auth_headers(admin) }
describe "GET /api/v1/users" do
it "returns paginated active users" do
create_list(:user, 3)
get "/api/v1/users", headers: headers
expect(response).to have_http_status(:ok)
expect(json_response.size).to eq(3)
end
end
describe "POST /api/v1/users" do
let(:valid_params) { { user: attributes_for(:user) } }
it "creates user and enqueues welcome email" do
expect {
post "/api/v1/users", params: valid_params, headers: headers
}.to change(User, :count).by(1)
.and have_enqueued_mail(UserMailer, :welcome_email)
expect(response).to have_http_status(:created)
end
end
end
Background Jobs
# app/jobs/export_users_job.rb
class ExportUsersJob < ApplicationJob
queue_as :default
retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
discard_on ActiveJob::DeserializationError
def perform(user_id, format: "csv")
user = User.find(user_id)
export = UserExportService.new(user, format:).call
UserMailer.export_ready(user, export.url).deliver_later
end
end
# Enqueue from controller or service
ExportUsersJob.perform_later(current_user.id, format: "csv")
Best Practices
DO
- Run
bundle exec rubocopand follow the Ruby Style Guide. - Use
find_eachinstead ofeachwhen iterating over large record sets (batches of 1000). - Add database indexes for columns used in
WHERE,ORDER BY, andJOINclauses. - Use
freezeon string constants to avoid allocations:ROLE_ADMIN = "admin".freeze. - Scope secrets with
Rails.application.credentials(encrypted) — never commit.envfiles. - Write request specs over controller specs — they test the full middleware stack.
- Use
ActiveRecord::Base.transactionfor operations that must succeed or fail together.
DON'T
- DON'T use
update_allordelete_allwithout understanding they skip callbacks and validations. - DON'T put query logic in views or controllers — use scopes or query objects.
- DON'T use
default_scope— it's global and nearly impossible to override cleanly. - DON'T call
.counton preloaded associations — use.size(which uses the preloaded data) or
.length.
- DON'T use
after_savecallbacks for side effects like sending emails — use service objects or
jobs.
- DON'T write migrations that are not reversible — always provide
upanddownor use reversible
methods.
- DON'T skip
null: falseconstraints in migrations when the model validates presence — the DB is
the last line of defense.
Rails Console Tips
# Reload code without restarting
reload!
# Show SQL queries in console
ActiveRecord::Base.logger = Logger.new(STDOUT)
# Find slow queries
User.includes(:posts).where(active: true).explain
# Sandbox mode — rolls back all changes on exit
# rails console --sandbox
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: dallay
- Source: dallay/agents-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.