74 lines
3.4 KiB
Markdown
74 lines
3.4 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Parsley is a personal recipe manager and meal planning app. It is a monolithic Rails 7.2 application with a Vue 3 SPA frontend.
|
|
|
|
**Backend:** Ruby 4.0.2, Rails 8.1.3, SQLite (dev/test), PostgreSQL (production)
|
|
**Frontend:** Vue 3 (Composition API / `<script setup>`), Pinia, Vue Router 4, Bulma CSS
|
|
**Asset bundling:** Shakapacker 8 (Webpack 5 + SWC)
|
|
**Testing:** RSpec, FactoryBot, Guard
|
|
|
|
## Common Commands
|
|
|
|
```bash
|
|
# Development
|
|
foreman start # Start Rails + Shakapacker dev server together
|
|
|
|
# Dependencies
|
|
bundle install && yarn install
|
|
|
|
# Database
|
|
bundle exec rake db:create db:migrate db:seed
|
|
bundle exec rake db:reset # Drop, recreate, seed
|
|
|
|
# Tests
|
|
bundle exec rspec # All tests
|
|
bundle exec rspec spec/models/recipe_spec.rb # Single file
|
|
bundle exec rspec spec/models/recipe_spec.rb:42 # Single test by line
|
|
bundle exec guard # Watch mode
|
|
|
|
# Build
|
|
bundle exec rake shakapacker:compile # Compile assets for production
|
|
```
|
|
|
|
**Test environment note:** Set `FAST=true` to skip FactoryBot linting on startup.
|
|
|
|
## Architecture
|
|
|
|
### Backend
|
|
|
|
**Models follow an `Ingredient` abstraction:** `Recipe` and `Food` both inherit from an abstract `Ingredient` base class. This allows recipes to contain both foods and other recipes as ingredients (`RecipeIngredient` is a polymorphic join). Polymorphic ingredient IDs are encoded as strings: `F{id}` for foods, `R{id}` for recipes.
|
|
|
|
**Custom unit conversion library** (`lib/unit_conversion/`): The `UnitConversion` module handles all quantity parsing and conversion. It is density-aware (can convert volume ↔ mass if food density is known) and supports custom per-food units defined in `FoodUnit` records. Key entry points: `UnitConversion.parse`, `UnitConversion.auto_unit`, `UnitConversion.with_custom_units`.
|
|
|
|
**Recipe scaling:** Recipes can be scaled by a factor and converted between unit systems (standard/metric) and unit types (mass/volume). Cache keys incorporate scale and unit system: `recipes/{id}/{scale}/{system}/{unit}`. Memcache is optional; enable with `RAILS_USE_MEMCACHE=true`.
|
|
|
|
**USDA nutrition data:** The `UsdaImporter` (lib/) imports from `vendor/data/usda/` during `db:seed`. `UsdaFood`/`UsdaFoodWeight` tables are a read-only cache; `Food` records link to them and inherit nutritional data.
|
|
|
|
**Serializers** (`app/serializers/`) handle all JSON API responses.
|
|
|
|
### Frontend
|
|
|
|
Vue 3 components live in `app/javascript/components/`. They use `<script setup>` Composition API style. Pinia stores (`app/javascript/stores/`) hold global state. Vue Router (`app/javascript/router/`) manages navigation.
|
|
|
|
Page-level components are named `The*` (e.g., `TheRecipeList`, `TheFood`, `TheCalculator`). Shared UI primitives are named `App*` (e.g., `AppModal`, `AppAutocomplete`, `AppIcon`).
|
|
|
|
### Key Environment Variables
|
|
|
|
| Variable | Purpose |
|
|
|----------|---------|
|
|
| `RAILS_USE_MEMCACHE` | Enable Memcache caching |
|
|
| `RAILS_MEMCACHE_HOST` | Memcache host (default: `memcache`) |
|
|
| `PARSLEY_DB_HOST/USER/PG_PASSWORD/DB_NAME` | Production PostgreSQL config |
|
|
|
|
### Docker
|
|
|
|
`docker-compose up` starts PostgreSQL, Memcached, Nginx, and two Rails service instances. See `docker-compose.yml` and `Dockerfile`.
|
|
|
|
### Seed Data
|
|
|
|
Default dev user: username `dan`, password `qwerty`. Comes with sample recipes and foods.
|