# 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/`)