Files
yockboard/AGENTS.md

229 lines
5.7 KiB
Markdown

# AGENTS.md - Yockboard Development Guide
This document provides guidelines for agentic coding agents working on the Yockboard Rails application.
## Project Overview
- **Framework**: Ruby on Rails 8.1.2
- **Ruby Version**: 3.4.7
- **Database**: PostgreSQL
- **Testing**: Minitest (Rails default)
- **JavaScript**: Turbo + Stimulus with Importmap
## Build / Lint / Test Commands
### Development Server
```bash
./bin/dev # Start development server (alias for bin/rails server)
bin/rails server -p 3000
```
### Running Tests
```bash
# Run all tests
bin/rails test
# Run a single test file
bin/rails test test/models/user_test.rb
# Run a single test by name
bin/rails test test/models/user_test.rb -n test_user_validity
# Run system tests (browser-based)
bin/rails test:system
# Run tests in specific directory
bin/rails test test/controllers/
```
### Linting & Code Style
```bash
# Run RuboCop linter
bin/rubocop
# Run specific RuboCop check
bin/rubocop app/models/
# Auto-fix RuboCop issues
bin/rubocop -a
```
### Security Scanning
```bash
# Scan for Rails security vulnerabilities
bin/brakeman --no-pager
# Scan for known gem vulnerabilities
bin/bundler-audit
# Audit JS dependencies
bin/importmap audit
```
### Database
```bash
bin/rails db:create db:migrate # Setup database
bin/rails db:test:prepare # Prepare test database
bin/rails db:reset # Reset database
```
### CI Pipeline (in .github/workflows/ci.yml)
- `scan_ruby`: Brakeman + bundler-audit
- `scan_js`: Importmap audit
- `lint`: RuboCop
- `test`: Full test suite with PostgreSQL
- `system-test`: System/integration tests
## Code Style Guidelines
### General Philosophy
Follow the **Rails Omakase** style (via `rubocop-rails-omakase`). This is the default Rails team style.
### File Organization
- Models: `app/models/`
- Controllers: `app/controllers/`
- Views: `app/views/controller_name/`
- Helpers: `app/helpers/`
- Jobs: `app/jobs/`
- Mailers: `app/mailers/`
### Naming Conventions
- **Classes/Modules**: `PascalCase` (e.g., `UserAccount`, `OrderProcessor`)
- **Database tables**: `snake_case_plurals` (e.g., `user_accounts`, `orders`)
- **Files**: `snake_case.rb` (e.g., `user_account.rb`, `order_processor.rb`)
- **Methods/variables**: `snake_case` (e.g., `user_accounts`, `process_order`)
- **Boolean methods**: End with `?` (e.g., `valid?`, `confirmed?`)
- **Bang methods**: End with `!` for mutating variants (e.g., `save!`, `update!`)
- **Query methods**: End with `?` or use plural names (e.g., `admin?`, `users`)
### Routing
- Use RESTful routes with `resources` when applicable
- Use namespace for admin/API routes
- Prefer shallow nesting: `resources :posts, shallow: true do resources :comments end`
### Models
- Inherit from `ApplicationRecord`
- Use concerns for shared behavior in `app/models/concerns/`
- Define associations explicitly
- Use scopes for common queries
```ruby
class User < ApplicationRecord
has_many :posts, dependent: :destroy
scope :active, -> { where(active: true) }
def full_name
"#{first_name} #{last_name}".strip
end
end
```
### Controllers
- Inherit from `ApplicationController`
- Use strong parameters for mass assignment
- Follow RESTful actions pattern
- Keep controllers thin; push logic to models/services
```ruby
class UsersController < ApplicationController
def index
@users = User.active.order(:created_at)
end
def create
@user = User.new(user_params)
if @user.save
redirect_to @user, notice: "User created"
else
render :new, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email)
end
end
```
### Views
- Use ERB with HTML
- Use Turbo Frames/Streams for SPA-like behavior
- Prefer Stimulus controllers over vanilla JS
- Use partials for reusable components
### Testing (Minitest)
- Test files go in `test/` mirroring `app/` structure
- Use `test/test_helper.rb` for shared setup
- Use fixtures in `test/fixtures/` for test data
```ruby
require "test_helper"
class UserTest < ActiveSupport::TestCase
test "valid user" do
user = User.new(email: "test@example.com", name: "Test")
assert user.valid?
end
test "invalid without email" do
user = User.new(name: "Test")
assert_not user.valid?
assert_includes user.errors[:email], "must be present"
end
end
```
### Error Handling
- Use ` rescue` blocks for expected errors
- Use `fail` or `raise` for unexpected states
- Flash messages for user feedback
- Render appropriate HTTP status codes
### Database
- Use migrations for schema changes: `bin/rails generate migration AddFieldToTable`
- Use `change` method for reversible migrations
- Add indexes for foreign keys and frequently queried columns
### Dependencies
- Add gems to appropriate groups in `Gemfile`
- Run `bundle install` after adding gems
- Use `Gemfile.lock` for reproducible builds
### Git Conventions
- Write clear, concise commit messages
- Create feature branches for new work
- Run linter and tests before committing
## Important File Locations
- Routes: `config/routes.rb`
- Application config: `config/application.rb`
- Environment configs: `config/environments/`
- Database config: `config/database.yml`
- Test config: `test/test_helper.rb`
## Common Tasks
### Generate New Resource
```bash
bin/rails generate scaffold ModelName field:type field:type
bin/rails db:migrate
```
### Run Specific Gem Command
```bash
bundle exec brakeman --no-pager
bundle exec rubocop
bundle exec rails test
```
## Notes
- This project uses **Solid** gems for cache/queue/cable (SolidCache, SolidQueue, SolidCable)
- Asset pipeline: Propshaft (Rails 8 default)
- JS: Importmap with Turbo and Stimulus
- Deployment: Kamal (see `.kamal/`)