parsley/CLAUDE.md

3.4 KiB

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

# 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.