Skip to content
This repository was archived by the owner on Jul 27, 2025. It is now read-only.

Commit fcf14f5

Browse files
committed
Add pre-pull request flow for Claude code
1 parent 63d8114 commit fcf14f5

File tree

1 file changed

+132
-31
lines changed

1 file changed

+132
-31
lines changed

CLAUDE.md

Lines changed: 132 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
1212
### Testing
1313
- `bin/rails test` - Run all tests
1414
- `bin/rails test:db` - Run tests with database reset
15-
- `bin/rails test:system` - Run system tests only
15+
- `bin/rails test:system` - Run system tests only (use sparingly - they take longer)
1616
- `bin/rails test test/models/account_test.rb` - Run specific test file
1717
- `bin/rails test test/models/account_test.rb:42` - Run specific test at line
1818

@@ -32,6 +32,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
3232
### Setup
3333
- `bin/setup` - Initial project setup (installs dependencies, prepares database)
3434

35+
## Pre-Pull Request CI Workflow
36+
37+
ALWAYS run these commands before opening a pull request:
38+
39+
1. **Tests** (Required):
40+
- `bin/rails test` - Run all tests (always required)
41+
- `bin/rails test:system` - Run system tests (only when applicable, they take longer)
42+
43+
2. **Linting** (Required):
44+
- `bin/rubocop -f github -a` - Ruby linting with auto-correct
45+
- `bundle exec erb_lint ./app/**/*.erb -a` - ERB linting with auto-correct
46+
47+
3. **Security** (Required):
48+
- `bin/brakeman --no-pager` - Security analysis
49+
50+
Only proceed with pull request creation if ALL checks pass.
51+
3552
## General Development Rules
3653

3754
### Authentication Context
@@ -110,13 +127,6 @@ Sidekiq handles asynchronous tasks:
110127
- Scoped permissions system for API access
111128
- Strong parameters and CSRF protection throughout
112129

113-
### Key Service Objects & Patterns
114-
- **Query Objects**: Complex database queries isolated in `app/queries/`
115-
- **Service Objects**: Business logic in `app/services/`
116-
- **Form Objects**: Complex forms with validation
117-
- **Concerns**: Shared functionality across models/controllers
118-
- **Jobs**: Background processing logic
119-
120130
### Testing Philosophy
121131
- Comprehensive test coverage using Rails' built-in Minitest
122132
- Fixtures for test data (avoid FactoryBot)
@@ -145,28 +155,119 @@ Sidekiq handles asynchronous tasks:
145155

146156
### Convention 1: Minimize Dependencies
147157
- Push Rails to its limits before adding new dependencies
148-
- When adding dependencies, favor old and reliable over new and flashy
149-
- Strong technical or business reason required for new dependencies
150-
151-
### Convention 2: POROs and Concerns over Service Objects
152-
- "Skinny controller, fat models" convention
153-
- Everything in `app/models/` folder, avoid separate folders like `app/services/`
154-
- Use Rails concerns for better organization (can be one-off concerns)
155-
- Models should answer questions about themselves (e.g., `account.balance_series`)
156-
157-
### Convention 3: Leverage Hotwire and Server-Side Solutions
158-
- Native HTML preferred over JS components (e.g., `<dialog>`, `<details>`)
159-
- Use Turbo frames to break up pages
160-
- Leverage query params for state over local storage
161-
- Format values server-side, pass to Stimulus for display only
162-
- Client-side code only where it truly shines (e.g., bulk selections)
163-
164-
### Convention 4: Optimize for Simplicity and Clarity
158+
- Strong technical/business reason required for new dependencies
159+
- Favor old and reliable over new and flashy
160+
161+
### Convention 2: Skinny Controllers, Fat Models
162+
- Business logic in `app/models/` folder, avoid `app/services/`
163+
- Use Rails concerns and POROs for organization
164+
- Models should answer questions about themselves: `account.balance_series` not `AccountSeries.new(account).call`
165+
166+
### Convention 3: Hotwire-First Frontend
167+
- **Native HTML preferred over JS components**
168+
- Use `<dialog>` for modals, `<details><summary>` for disclosures
169+
- **Leverage Turbo frames** for page sections over client-side solutions
170+
- **Query params for state** over localStorage/sessions
171+
- **Server-side formatting** for currencies, numbers, dates
172+
- **Always use `icon` helper** in `application_helper.rb`, NEVER `lucide_icon` directly
173+
174+
### Convention 4: Optimize for Simplicity
165175
- Prioritize good OOP domain design over performance
166-
- Only focus on performance in critical/global areas
167-
- Be mindful of N+1 queries and large data payloads
176+
- Focus performance only on critical/global areas (avoid N+1 queries, mindful of global layouts)
177+
178+
### Convention 5: Database vs ActiveRecord Validations
179+
- Simple validations (null checks, unique indexes) in DB
180+
- ActiveRecord validations for convenience in forms (prefer client-side when possible)
181+
- Complex validations and business logic in ActiveRecord
182+
183+
## TailwindCSS Design System
184+
185+
### Design System Rules
186+
- **Always reference `app/assets/tailwind/maybe-design-system.css`** for primitives and tokens
187+
- **Use functional tokens** defined in design system:
188+
- `text-primary` instead of `text-white`
189+
- `bg-container` instead of `bg-white`
190+
- `border border-primary` instead of `border border-gray-200`
191+
- **NEVER create new styles** in design system files without permission
192+
- **Always generate semantic HTML**
193+
194+
## Component Architecture
195+
196+
### ViewComponent vs Partials Decision Making
197+
198+
**Use ViewComponents when:**
199+
- Element has complex logic or styling patterns
200+
- Element will be reused across multiple views/contexts
201+
- Element needs structured styling with variants/sizes
202+
- Element requires interactive behavior or Stimulus controllers
203+
- Element has configurable slots or complex APIs
204+
- Element needs accessibility features or ARIA support
205+
206+
**Use Partials when:**
207+
- Element is primarily static HTML with minimal logic
208+
- Element is used in only one or few specific contexts
209+
- Element is simple template content
210+
- Element doesn't need variants, sizes, or complex configuration
211+
- Element is more about content organization than reusable functionality
212+
213+
**Component Guidelines:**
214+
- Prefer components over partials when available
215+
- Keep domain logic OUT of view templates
216+
- Logic belongs in component files, not template files
217+
218+
### Stimulus Controller Guidelines
219+
220+
**Declarative Actions (Required):**
221+
```erb
222+
<!-- GOOD: Declarative - HTML declares what happens -->
223+
<div data-controller="toggle">
224+
<button data-action="click->toggle#toggle" data-toggle-target="button">Show</button>
225+
<div data-toggle-target="content" class="hidden">Hello World!</div>
226+
</div>
227+
```
228+
229+
**Controller Best Practices:**
230+
- Keep controllers lightweight and simple (< 7 targets)
231+
- Use private methods and expose clear public API
232+
- Single responsibility or highly related responsibilities
233+
- Component controllers stay in component directory, global controllers in `app/javascript/controllers/`
234+
- Pass data via `data-*-value` attributes, not inline JavaScript
235+
236+
## Testing Philosophy
237+
238+
### General Testing Rules
239+
- **ALWAYS use Minitest + fixtures** (NEVER RSpec or factories)
240+
- Keep fixtures minimal (2-3 per model for base cases)
241+
- Create edge cases on-the-fly within test context
242+
- Use Rails helpers for large fixture creation needs
243+
244+
### Test Quality Guidelines
245+
- **Write minimal, effective tests** - system tests sparingly
246+
- **Only test critical and important code paths**
247+
- **Test boundaries correctly:**
248+
- Commands: test they were called with correct params
249+
- Queries: test output
250+
- Don't test implementation details of other classes
251+
252+
### Testing Examples
253+
254+
```ruby
255+
# GOOD - Testing critical domain business logic
256+
test "syncs balances" do
257+
Holding::Syncer.any_instance.expects(:sync_holdings).returns([]).once
258+
assert_difference "@account.balances.count", 2 do
259+
Balance::Syncer.new(@account, strategy: :forward).sync_balances
260+
end
261+
end
262+
263+
# BAD - Testing ActiveRecord functionality
264+
test "saves balance" do
265+
balance_record = Balance.new(balance: 100, currency: "USD")
266+
assert balance_record.save
267+
end
268+
```
168269

169-
### Convention 5: ActiveRecord for Complex Validations, DB for Simple Ones
170-
- Enforce null checks, unique indexes in the DB
171-
- ActiveRecord validations for convenience in forms
172-
- Complex validations and business logic in ActiveRecord
270+
### Stubs and Mocks
271+
- Use `mocha` gem
272+
- Prefer `OpenStruct` for mock instances
273+
- Only mock what's necessary

0 commit comments

Comments
 (0)