install
SKILL.md
Rails 8 Application Setup
Overview
Bootstrap a new Rails 8 application with production-ready defaults:
- Rails 8 with Solid Queue, Solid Cache, Solid Cable
- Built-in authentication (has_secure_password)
- Multi-tenancy via Account scoping
- Hotwire (Turbo + Stimulus)
- Minitest + fixtures for testing
- Tailwind CSS for styling
Quick Start
rails new myapp --css tailwind --database sqlite3
cd myapp
Post-Generation Setup
1. Generate Authentication
bin/rails generate authentication
bin/rails db:migrate
This creates:
Usermodel withemail_addressandpassword_digestSessionmodel with token-based sessionsCurrentmodel (CurrentAttributes)AuthenticationconcernSessionsController
2. Add Account Model (Multi-Tenancy)
bin/rails generate model Account name:string
bin/rails generate migration AddAccountToUsers account:references
bin/rails db:migrate
# app/models/account.rb
class Account < ApplicationRecord
has_many :users, dependent: :destroy
validates :name, presence: true
end
# app/models/user.rb
class User < ApplicationRecord
has_secure_password
has_many :sessions, dependent: :destroy
belongs_to :account
normalizes :email_address, with: ->(e) { e.strip.downcase }
validates :email_address, presence: true,
uniqueness: true,
format: { with: URI::MailTo::EMAIL_REGEXP }
end
3. Add Current Account
# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
attribute :session
attribute :user_agent, :ip_address
delegate :user, to: :session, allow_nil: true
def account
user&.account
end
end
4. Configure Test Helper
# test/test_helper.rb
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
module ActiveSupport
class TestCase
parallelize(workers: :number_of_processors)
fixtures :all
private
def sign_in(user)
session = user.sessions.create!
cookies.signed.permanent[:session_token] = {
value: session.token,
httponly: true
}
Current.session = session
end
def sign_out
Current.session&.destroy
cookies.delete(:session_token)
end
end
end
5. Create Fixtures
# test/fixtures/accounts.yml
one:
name: Acme Corp
other:
name: Other Corp
# test/fixtures/users.yml
one:
email_address: user@example.com
password_digest: <%= BCrypt::Password.create("password123") %>
account: one
admin:
email_address: admin@example.com
password_digest: <%= BCrypt::Password.create("password123") %>
account: one
other_account:
email_address: other@example.com
password_digest: <%= BCrypt::Password.create("password123") %>
account: other
# test/fixtures/sessions.yml
one:
user: one
token: <%= SecureRandom.urlsafe_base64(32) %>
6. Configure Solid Queue
# config/queue.yml (already generated by Rails 8)
default: &default
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 3
processes: 1
polling_interval: 0.1
# config/environments/production.rb
config.active_job.queue_adapter = :solid_queue
config.solid_queue.connects_to = { database: { writing: :queue } }
7. Configure Solid Cache
# config/environments/production.rb
config.cache_store = :solid_cache_store
config.solid_cache.connects_to = { database: { writing: :cache } }
8. Add Development Gems
# Gemfile
group :development, :test do
gem "debug", platforms: %i[mri windows], require: "debug/prelude"
gem "brakeman", require: false
gem "rubocop-rails-omakase", require: false
gem "bullet"
end
bundle install
9. Configure Bullet (N+1 Detection)
# config/environments/development.rb
config.after_initialize do
Bullet.enable = true
Bullet.alert = true
Bullet.bullet_logger = true
Bullet.console = true
Bullet.rails_logger = true
end
# config/environments/test.rb
config.after_initialize do
Bullet.enable = true
Bullet.raise = true
end
10. Add Application Layout Defaults
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "MyApp" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body class="min-h-screen bg-white">
<div id="flash">
<% flash.each do |type, message| %>
<div class="flash flash-<%= type %>"><%= message %></div>
<% end %>
</div>
<main class="container mx-auto px-4 py-8">
<%= yield %>
</main>
</body>
</html>
Verification
Run the test suite to confirm everything is wired up:
bin/rails test
Smoke Test
# test/models/user_test.rb
require "test_helper"
class UserTest < ActiveSupport::TestCase
test "fixture user is valid" do
user = users(:one)
assert user.valid?
end
test "requires email_address" do
user = User.new(password: "password123", account: accounts(:one))
assert_not user.valid?
assert user.errors[:email_address].any?
end
test "requires unique email_address" do
existing = users(:one)
user = User.new(
email_address: existing.email_address,
password: "password123",
account: accounts(:one)
)
assert_not user.valid?
assert user.errors[:email_address].any?
end
end
# test/models/account_test.rb
require "test_helper"
class AccountTest < ActiveSupport::TestCase
test "fixture account is valid" do
account = accounts(:one)
assert account.valid?
end
test "requires name" do
account = Account.new
assert_not account.valid?
assert account.errors[:name].any?
end
end
Directory Structure After Setup
app/
├── controllers/
│ ├── application_controller.rb
│ ├── concerns/
│ │ └── authentication.rb
│ └── sessions_controller.rb
├── models/
│ ├── account.rb
│ ├── current.rb
│ ├── session.rb
│ └── user.rb
├── views/
│ └── layouts/
│ └── application.html.erb
config/
├── database.yml
├── queue.yml
├── cable.yml
└── environments/
├── development.rb
├── production.rb
└── test.rb
test/
├── test_helper.rb
├── fixtures/
│ ├── accounts.yml
│ ├── users.yml
│ └── sessions.yml
└── models/
├── user_test.rb
└── account_test.rb
Rails 8 Defaults
Rails 8 ships with these defaults already configured:
- Solid Queue - Database-backed Active Job backend (replaces Redis/Sidekiq)
- Solid Cache - Database-backed cache store (replaces Redis/Memcached)
- Solid Cable - Database-backed Action Cable adapter
- Propshaft - Asset pipeline (replaces Sprockets)
- Import Maps - JavaScript without bundling
- Kamal - Deployment
- Thruster - HTTP/2 proxy with asset caching
Checklist
- Rails app generated
- Authentication generated and migrated
- Account model created (multi-tenancy)
- Current model configured with account
- Test helper with sign_in/sign_out
- Fixtures created (accounts, users, sessions)
- Solid Queue configured
- Solid Cache configured
- Bullet configured for N+1 detection
- Smoke tests pass
- All tests GREEN
Weekly Installs
2
Repository
dchuk/rails_ai_agentsFirst Seen
7 days ago
Security Audits
Installed on
opencode2
gemini-cli2
antigravity2
claude-code2
windsurf2
codex2