Dep upgrades; bug fixes
This commit is contained in:
parent
28baaa3c3d
commit
df99f800b9
@ -6,4 +6,5 @@ public/assets
|
||||
public/packs
|
||||
node_modules/
|
||||
.yarn
|
||||
.pnp.*
|
||||
.pnp.*
|
||||
.claude
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -36,4 +36,5 @@ yarn-debug.log*
|
||||
yarn-debug.log*
|
||||
.yarn-integrity
|
||||
.yarn
|
||||
.pnp.*
|
||||
.pnp.*
|
||||
.claude
|
||||
@ -1 +1 @@
|
||||
3.3.5
|
||||
4.0.2
|
||||
|
||||
73
CLAUDE.md
Normal file
73
CLAUDE.md
Normal file
@ -0,0 +1,73 @@
|
||||
# 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.
|
||||
@ -1,8 +1,9 @@
|
||||
FROM ruby:3.3.5-bookworm
|
||||
FROM ruby:4.0.2-trixie
|
||||
|
||||
RUN curl -sL https://deb.nodesource.com/setup_lts.x | bash - && \
|
||||
apt-get update && apt-get dist-upgrade -y && \
|
||||
apt-get install -y \
|
||||
pkg-config \
|
||||
nodejs \
|
||||
nginx && \
|
||||
apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
2
Gemfile
2
Gemfile
@ -1,6 +1,6 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '7.2.1'
|
||||
gem 'rails', '8.1.3'
|
||||
gem 'pg', '~> 1.5.8'
|
||||
|
||||
gem 'shakapacker', '8.0.2'
|
||||
|
||||
288
Gemfile.lock
288
Gemfile.lock
@ -1,106 +1,112 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
action_text-trix (2.1.18)
|
||||
railties
|
||||
actioncable (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
activejob (= 7.2.1)
|
||||
activerecord (= 7.2.1)
|
||||
activestorage (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
actionmailbox (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
activejob (= 8.1.3)
|
||||
activerecord (= 8.1.3)
|
||||
activestorage (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
mail (>= 2.8.0)
|
||||
actionmailer (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
actionview (= 7.2.1)
|
||||
activejob (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
actionmailer (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
actionview (= 8.1.3)
|
||||
activejob (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
mail (>= 2.8.0)
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.2.1)
|
||||
actionview (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
actionpack (8.1.3)
|
||||
actionview (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4, < 3.2)
|
||||
rack (>= 2.2.4)
|
||||
rack-session (>= 1.0.1)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
useragent (~> 0.16)
|
||||
actiontext (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
activerecord (= 7.2.1)
|
||||
activestorage (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
actiontext (8.1.3)
|
||||
action_text-trix (~> 2.1.15)
|
||||
actionpack (= 8.1.3)
|
||||
activerecord (= 8.1.3)
|
||||
activestorage (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
actionview (8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
activejob (7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
activejob (8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
activerecord (7.2.1)
|
||||
activemodel (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
activemodel (8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
activerecord (8.1.3)
|
||||
activemodel (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
timeout (>= 0.4.0)
|
||||
activestorage (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
activejob (= 7.2.1)
|
||||
activerecord (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
activestorage (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
activejob (= 8.1.3)
|
||||
activerecord (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
marcel (~> 1.0)
|
||||
activesupport (7.2.1)
|
||||
activesupport (8.1.3)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
json
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
base64 (0.2.0)
|
||||
bcrypt (3.1.20)
|
||||
bigdecimal (3.1.8)
|
||||
bootsnap (1.18.4)
|
||||
uri (>= 0.13.1)
|
||||
base64 (0.3.0)
|
||||
bcrypt (3.1.22)
|
||||
bigdecimal (4.1.2)
|
||||
bootsnap (1.23.0)
|
||||
msgpack (~> 1.2)
|
||||
builder (3.3.0)
|
||||
coderay (1.1.3)
|
||||
concurrent-ruby (1.3.4)
|
||||
connection_pool (2.4.1)
|
||||
concurrent-ruby (1.3.6)
|
||||
connection_pool (3.0.2)
|
||||
crass (1.0.6)
|
||||
csv (3.3.0)
|
||||
csv (3.3.5)
|
||||
dalli (3.2.8)
|
||||
database_cleaner (2.0.2)
|
||||
database_cleaner-active_record (>= 2, < 3)
|
||||
database_cleaner-active_record (2.2.0)
|
||||
database_cleaner-active_record (2.2.2)
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (~> 2.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
date (3.3.4)
|
||||
diff-lcs (1.5.1)
|
||||
drb (2.2.1)
|
||||
erubi (1.13.0)
|
||||
factory_bot (6.5.0)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.4.3)
|
||||
factory_bot (~> 6.4)
|
||||
date (3.5.1)
|
||||
diff-lcs (1.6.2)
|
||||
drb (2.2.3)
|
||||
erb (6.0.3)
|
||||
erubi (1.13.1)
|
||||
factory_bot (6.5.6)
|
||||
activesupport (>= 6.1.0)
|
||||
factory_bot_rails (6.4.4)
|
||||
factory_bot (~> 6.5)
|
||||
railties (>= 5.0.0)
|
||||
ffi (1.17.0)
|
||||
formatador (1.1.0)
|
||||
globalid (1.2.1)
|
||||
ffi (1.17.4)
|
||||
formatador (1.2.3)
|
||||
reline
|
||||
globalid (1.3.0)
|
||||
activesupport (>= 6.1)
|
||||
guard (2.18.1)
|
||||
formatador (>= 0.2.4)
|
||||
@ -116,12 +122,15 @@ GEM
|
||||
guard (~> 2.1)
|
||||
guard-compat (~> 1.1)
|
||||
rspec (>= 2.99.0, < 4.0)
|
||||
i18n (1.14.6)
|
||||
i18n (1.14.8)
|
||||
concurrent-ruby (~> 1.0)
|
||||
io-console (0.7.2)
|
||||
irb (1.14.1)
|
||||
io-console (0.8.2)
|
||||
irb (1.17.0)
|
||||
pp (>= 0.6.0)
|
||||
prism (>= 1.3.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
json (2.19.4)
|
||||
kaminari (1.2.2)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.2.2)
|
||||
@ -135,124 +144,136 @@ GEM
|
||||
kaminari-core (= 1.2.2)
|
||||
kaminari-core (1.2.2)
|
||||
liner (0.2.4)
|
||||
listen (3.9.0)
|
||||
listen (3.10.0)
|
||||
logger
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.6.1)
|
||||
loofah (2.22.0)
|
||||
logger (1.7.0)
|
||||
loofah (2.25.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
lumberjack (1.2.10)
|
||||
mail (2.8.1)
|
||||
lumberjack (1.4.2)
|
||||
mail (2.9.0)
|
||||
logger
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
marcel (1.0.4)
|
||||
memoizable (0.4.2)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
marcel (1.1.0)
|
||||
memoizable (0.5.1)
|
||||
method_source (1.1.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.7)
|
||||
minitest (5.25.1)
|
||||
msgpack (1.7.2)
|
||||
mini_portile2 (2.8.9)
|
||||
minitest (6.0.4)
|
||||
drb (~> 2.0)
|
||||
prism (~> 1.5)
|
||||
msgpack (1.8.0)
|
||||
nenv (0.3.0)
|
||||
net-imap (0.4.16)
|
||||
net-imap (0.6.3)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
nio4r (2.7.3)
|
||||
nokogiri (1.16.7)
|
||||
nio4r (2.7.5)
|
||||
nokogiri (1.19.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
notiffany (0.1.3)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
oj (3.16.6)
|
||||
oj (3.16.17)
|
||||
bigdecimal (>= 3.0)
|
||||
ostruct (>= 0.2)
|
||||
ostruct (0.6.0)
|
||||
package_json (0.1.0)
|
||||
ostruct (0.6.3)
|
||||
package_json (0.2.0)
|
||||
parslet (2.0.0)
|
||||
pg (1.5.8)
|
||||
pry (0.14.2)
|
||||
pg (1.5.9)
|
||||
pp (0.6.3)
|
||||
prettyprint
|
||||
prettyprint (0.2.0)
|
||||
prism (1.9.0)
|
||||
pry (0.16.0)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
psych (5.1.2)
|
||||
reline (>= 0.6.0)
|
||||
psych (5.3.1)
|
||||
date
|
||||
stringio
|
||||
puma (6.4.3)
|
||||
puma (6.6.1)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.8.1)
|
||||
rack (3.1.7)
|
||||
rack (3.2.6)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-session (2.0.0)
|
||||
rack-session (2.1.2)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rack-test (2.1.0)
|
||||
rack-test (2.2.0)
|
||||
rack (>= 1.3)
|
||||
rackup (2.1.0)
|
||||
rackup (2.3.1)
|
||||
rack (>= 3)
|
||||
webrick (~> 1.8)
|
||||
rails (7.2.1)
|
||||
actioncable (= 7.2.1)
|
||||
actionmailbox (= 7.2.1)
|
||||
actionmailer (= 7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
actiontext (= 7.2.1)
|
||||
actionview (= 7.2.1)
|
||||
activejob (= 7.2.1)
|
||||
activemodel (= 7.2.1)
|
||||
activerecord (= 7.2.1)
|
||||
activestorage (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
rails (8.1.3)
|
||||
actioncable (= 8.1.3)
|
||||
actionmailbox (= 8.1.3)
|
||||
actionmailer (= 8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
actiontext (= 8.1.3)
|
||||
actionview (= 8.1.3)
|
||||
activejob (= 8.1.3)
|
||||
activemodel (= 8.1.3)
|
||||
activerecord (= 8.1.3)
|
||||
activestorage (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.2.1)
|
||||
railties (= 8.1.3)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
activesupport (>= 5.0.1.rc1)
|
||||
rails-dom-testing (2.2.0)
|
||||
rails-dom-testing (2.3.0)
|
||||
activesupport (>= 5.0.0)
|
||||
minitest
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.6.0)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
railties (7.2.1)
|
||||
actionpack (= 7.2.1)
|
||||
activesupport (= 7.2.1)
|
||||
rails-html-sanitizer (1.7.0)
|
||||
loofah (~> 2.25)
|
||||
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
||||
railties (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
irb (~> 1.13)
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
tsort (>= 0.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rake (13.2.1)
|
||||
rake (13.4.2)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rdoc (6.7.0)
|
||||
rdoc (7.2.0)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
redcarpet (3.6.0)
|
||||
reline (0.5.10)
|
||||
tsort
|
||||
redcarpet (3.6.1)
|
||||
reline (0.6.3)
|
||||
io-console (~> 0.5)
|
||||
rspec (3.13.0)
|
||||
rspec (3.13.2)
|
||||
rspec-core (~> 3.13.0)
|
||||
rspec-expectations (~> 3.13.0)
|
||||
rspec-mocks (~> 3.13.0)
|
||||
rspec-core (3.13.1)
|
||||
rspec-core (3.13.6)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.3)
|
||||
rspec-expectations (3.13.5)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-mocks (3.13.1)
|
||||
rspec-mocks (3.13.8)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (7.0.1)
|
||||
rspec-rails (7.0.2)
|
||||
actionpack (>= 7.0)
|
||||
activesupport (>= 7.0)
|
||||
railties (>= 7.0)
|
||||
@ -260,9 +281,9 @@ GEM
|
||||
rspec-expectations (~> 3.13)
|
||||
rspec-mocks (~> 3.13)
|
||||
rspec-support (~> 3.13)
|
||||
rspec-support (3.13.1)
|
||||
securerandom (0.3.1)
|
||||
semantic_range (3.0.0)
|
||||
rspec-support (3.13.7)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.1.1)
|
||||
shakapacker (8.0.2)
|
||||
activesupport (>= 5.2)
|
||||
package_json
|
||||
@ -271,27 +292,28 @@ GEM
|
||||
semantic_range (>= 2.3.0)
|
||||
shellany (0.0.1)
|
||||
signed_multiset (0.2.1)
|
||||
sqlite3 (2.1.0)
|
||||
sqlite3 (2.1.1)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
stringio (3.1.1)
|
||||
thor (1.3.2)
|
||||
thread_safe (0.3.6)
|
||||
timeout (0.4.1)
|
||||
stringio (3.2.0)
|
||||
thor (1.5.0)
|
||||
timeout (0.6.1)
|
||||
tsort (0.2.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
tzinfo-data (1.2024.2)
|
||||
tzinfo-data (1.2026.1)
|
||||
tzinfo (>= 1.0.0)
|
||||
unitwise (2.3.0)
|
||||
liner (~> 0.2)
|
||||
memoizable (~> 0.4)
|
||||
parslet (~> 2.0)
|
||||
signed_multiset (~> 0.2)
|
||||
useragent (0.16.10)
|
||||
webrick (1.8.2)
|
||||
websocket-driver (0.7.6)
|
||||
uri (1.1.1)
|
||||
useragent (0.16.11)
|
||||
websocket-driver (0.8.0)
|
||||
base64
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
zeitwerk (2.6.18)
|
||||
zeitwerk (2.7.5)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@ -309,7 +331,7 @@ DEPENDENCIES
|
||||
oj (~> 3.16.6)
|
||||
pg (~> 1.5.8)
|
||||
puma (~> 6.4)
|
||||
rails (= 7.2.1)
|
||||
rails (= 8.1.3)
|
||||
rails-controller-testing
|
||||
redcarpet (~> 3.6.0)
|
||||
rspec-rails (~> 7.0.1)
|
||||
@ -319,4 +341,4 @@ DEPENDENCIES
|
||||
unitwise (~> 2.3.0)
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.20
|
||||
4.0.10
|
||||
|
||||
@ -42,7 +42,7 @@ class TaskItemsController < ApplicationController
|
||||
new_status = !params[:invert].present?
|
||||
TaskItem.transaction do
|
||||
@task_items = @task_list.task_items.find(ids)
|
||||
@task_items.each { |i| i.update_attribute(:completed, new_status) }
|
||||
@task_items.each { |i| i.update_column(:completed, new_status) }
|
||||
end
|
||||
|
||||
TaskChannel.update_task_list(@task_list)
|
||||
|
||||
@ -8,32 +8,27 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { ref } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import debounce from "lodash/debounce";
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
|
||||
modelValue: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
});
|
||||
|
||||
const text = ref(null);
|
||||
const model = defineModel({ type: String, default: null });
|
||||
const text = ref(model.value);
|
||||
|
||||
watch(model, (val) => { text.value = val; });
|
||||
|
||||
const triggerInput = debounce(function() {
|
||||
emit("update:modelValue", text.value);
|
||||
model.value = text.value;
|
||||
},
|
||||
250,
|
||||
{ leading: false, trailing: true })
|
||||
{ leading: false, trailing: true });
|
||||
|
||||
function userUpdateText(newText) {
|
||||
if (text.value !== newText) {
|
||||
@ -42,10 +37,4 @@ function userUpdateText(newText) {
|
||||
}
|
||||
}
|
||||
|
||||
function propUpdateText(newText) {
|
||||
if (text.value === null && text.value !== newText) {
|
||||
text.value = newText;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -87,10 +87,10 @@
|
||||
return api.getSearchIngredients(text);
|
||||
}
|
||||
|
||||
function searchItemSelected(ingredient) {
|
||||
ingredient.value = ingredient || null;
|
||||
ingredient_name.value = ingredient.name || null;
|
||||
density.value = ingredient.density || null;
|
||||
function searchItemSelected(selectedIngredient) {
|
||||
ingredient.value = selectedIngredient || null;
|
||||
ingredient_name.value = selectedIngredient.name || null;
|
||||
density.value = selectedIngredient.density || null;
|
||||
}
|
||||
|
||||
function getErrors(type) {
|
||||
|
||||
@ -25,10 +25,10 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<app-search-text placeholder="search names" :value="search.name" @update:modelValue="setSearchName($event)"></app-search-text>
|
||||
<app-search-text placeholder="search names" :model-value="search.name" @update:modelValue="setSearchName($event)"></app-search-text>
|
||||
</td>
|
||||
<td>
|
||||
<app-search-text placeholder="search tags" :value="search.tags" @update:modelValue="setSearchTags($event)"></app-search-text>
|
||||
<app-search-text placeholder="search tags" :model-value="search.tags" @update:modelValue="setSearchTags($event)"></app-search-text>
|
||||
</td>
|
||||
<td colspan="5"></td>
|
||||
</tr>
|
||||
|
||||
@ -9,7 +9,7 @@ class User < ApplicationRecord
|
||||
validates :username, presence: true, uniqueness: { case_sensitive: false }
|
||||
|
||||
def self.authenticate(username, password)
|
||||
find_by_username(username).try(:authenticate, password)
|
||||
find_by(username: username)&.authenticate(password)
|
||||
end
|
||||
|
||||
def display_name
|
||||
|
||||
@ -24,7 +24,7 @@ require_relative '../lib/unit_conversion'
|
||||
module Parsley
|
||||
class Application < Rails::Application
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 7.2
|
||||
config.load_defaults 8.0
|
||||
|
||||
config.autoload_lib(ignore: %w(assets tasks unit_conversion unit_conversion.rb))
|
||||
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
Rails.application.configure do
|
||||
# Verifies that versions and hashed value of the package contents in the project's package.json
|
||||
config.webpacker.check_yarn_integrity = false
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
config.enable_reloading = false
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
@ -68,8 +66,8 @@ Rails.application.configure do
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
# Don't log any deprecations.
|
||||
config.active_support.report_deprecations = false
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
@ -2,7 +2,7 @@ Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
config.enable_reloading = false
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
@ -56,8 +56,8 @@ Rails.application.configure do
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
# Don't log any deprecations.
|
||||
config.active_support.report_deprecations = false
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
178
db/schema.rb
178
db/schema.rb
@ -10,107 +10,107 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2018_09_15_134841) do
|
||||
ActiveRecord::Schema[8.1].define(version: 2018_09_15_134841) do
|
||||
create_table "food_units", force: :cascade do |t|
|
||||
t.integer "food_id", null: false
|
||||
t.string "name", null: false
|
||||
t.decimal "gram_weight", precision: 10, scale: 2, null: false
|
||||
t.string "name", null: false
|
||||
t.index ["food_id"], name: "index_food_units_on_food_id"
|
||||
end
|
||||
|
||||
create_table "foods", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "density"
|
||||
t.text "notes"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.string "ndbn", limit: 25
|
||||
t.decimal "water", precision: 10, scale: 2
|
||||
t.decimal "protein", precision: 10, scale: 2
|
||||
t.decimal "lipids", precision: 10, scale: 2
|
||||
t.decimal "ash", precision: 10, scale: 2
|
||||
t.decimal "carbohydrates", precision: 10, scale: 2
|
||||
t.integer "kcal"
|
||||
t.decimal "fiber", precision: 10, scale: 1
|
||||
t.decimal "sugar", precision: 10, scale: 2
|
||||
t.integer "user_id"
|
||||
t.integer "calcium"
|
||||
t.decimal "carbohydrates", precision: 10, scale: 2
|
||||
t.decimal "cholesterol", precision: 10, scale: 3
|
||||
t.decimal "copper", precision: 10, scale: 3
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "density"
|
||||
t.decimal "fiber", precision: 10, scale: 1
|
||||
t.decimal "iron", precision: 10, scale: 2
|
||||
t.integer "kcal"
|
||||
t.decimal "lipids", precision: 10, scale: 2
|
||||
t.integer "magnesium"
|
||||
t.decimal "manganese", precision: 10, scale: 3
|
||||
t.string "name"
|
||||
t.string "ndbn", limit: 25
|
||||
t.text "notes"
|
||||
t.integer "phosphorus"
|
||||
t.integer "potassium"
|
||||
t.decimal "protein", precision: 10, scale: 2
|
||||
t.integer "sodium"
|
||||
t.decimal "zinc", precision: 10, scale: 2
|
||||
t.decimal "copper", precision: 10, scale: 3
|
||||
t.decimal "manganese", precision: 10, scale: 3
|
||||
t.decimal "vit_c", precision: 10, scale: 1
|
||||
t.decimal "vit_b6", precision: 10, scale: 3
|
||||
t.decimal "vit_b12", precision: 10, scale: 2
|
||||
t.decimal "sugar", precision: 10, scale: 2
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "user_id"
|
||||
t.integer "vit_a"
|
||||
t.decimal "vit_e", precision: 10, scale: 2
|
||||
t.decimal "vit_b12", precision: 10, scale: 2
|
||||
t.decimal "vit_b6", precision: 10, scale: 3
|
||||
t.decimal "vit_c", precision: 10, scale: 1
|
||||
t.decimal "vit_d", precision: 10, scale: 1
|
||||
t.decimal "vit_e", precision: 10, scale: 2
|
||||
t.decimal "vit_k", precision: 10, scale: 1
|
||||
t.decimal "cholesterol", precision: 10, scale: 3
|
||||
t.decimal "water", precision: 10, scale: 2
|
||||
t.decimal "zinc", precision: 10, scale: 2
|
||||
t.index ["ndbn"], name: "index_foods_on_ndbn"
|
||||
end
|
||||
|
||||
create_table "logs", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "date", precision: nil
|
||||
t.text "notes"
|
||||
t.integer "rating"
|
||||
t.integer "recipe_id"
|
||||
t.integer "source_recipe_id"
|
||||
t.datetime "date", precision: nil
|
||||
t.integer "rating"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.text "notes"
|
||||
t.integer "user_id"
|
||||
end
|
||||
|
||||
create_table "notes", force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.text "content", null: false
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "user_id", null: false
|
||||
t.index ["user_id"], name: "index_notes_on_user_id"
|
||||
end
|
||||
|
||||
create_table "recipe_ingredients", force: :cascade do |t|
|
||||
t.integer "food_id"
|
||||
t.integer "recipe_id"
|
||||
t.string "name"
|
||||
t.integer "sort_order"
|
||||
t.string "quantity"
|
||||
t.string "units"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "food_id"
|
||||
t.string "name"
|
||||
t.text "preparation"
|
||||
t.string "quantity"
|
||||
t.integer "recipe_as_ingredient_id"
|
||||
t.integer "recipe_id"
|
||||
t.integer "sort_order"
|
||||
t.string "units"
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.index ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id"
|
||||
end
|
||||
|
||||
create_table "recipe_steps", force: :cascade do |t|
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.integer "recipe_id"
|
||||
t.integer "sort_order"
|
||||
t.text "step"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.index ["recipe_id"], name: "index_recipe_steps_on_recipe_id"
|
||||
end
|
||||
|
||||
create_table "recipes", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.text "description"
|
||||
t.text "source"
|
||||
t.string "yields"
|
||||
t.integer "total_time"
|
||||
t.integer "active_time"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.boolean "deleted"
|
||||
t.integer "user_id"
|
||||
t.boolean "is_log"
|
||||
t.float "rating"
|
||||
t.text "step_text"
|
||||
t.text "description"
|
||||
t.boolean "is_ingredient"
|
||||
t.boolean "is_log"
|
||||
t.string "name"
|
||||
t.float "rating"
|
||||
t.text "source"
|
||||
t.text "step_text"
|
||||
t.integer "total_time"
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "user_id"
|
||||
t.string "yields"
|
||||
end
|
||||
|
||||
create_table "recipes_tags", id: false, force: :cascade do |t|
|
||||
@ -121,94 +121,94 @@ ActiveRecord::Schema[7.2].define(version: 2018_09_15_134841) do
|
||||
end
|
||||
|
||||
create_table "tags", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "lowercase_name"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "lowercase_name"
|
||||
t.string "name"
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.index ["lowercase_name"], name: "index_tags_on_lowercase_name", unique: true
|
||||
end
|
||||
|
||||
create_table "task_items", force: :cascade do |t|
|
||||
t.integer "task_list_id", null: false
|
||||
t.boolean "completed"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "name"
|
||||
t.string "quantity"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.integer "task_list_id", null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.boolean "completed"
|
||||
t.index ["task_list_id"], name: "index_task_items_on_task_list_id"
|
||||
end
|
||||
|
||||
create_table "task_lists", force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.string "name"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "name"
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "user_id", null: false
|
||||
t.index ["user_id"], name: "index_task_lists_on_user_id"
|
||||
end
|
||||
|
||||
create_table "usda_food_weights", force: :cascade do |t|
|
||||
t.integer "usda_food_id", null: false
|
||||
t.decimal "amount", precision: 7, scale: 3
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "description"
|
||||
t.decimal "gram_weight", precision: 7, scale: 1
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "usda_food_id", null: false
|
||||
t.index ["usda_food_id"], name: "index_usda_food_weights_on_usda_food_id"
|
||||
end
|
||||
|
||||
create_table "usda_foods", force: :cascade do |t|
|
||||
t.string "ndbn", limit: 25
|
||||
t.string "long_description"
|
||||
t.string "short_description"
|
||||
t.decimal "water", precision: 10, scale: 2
|
||||
t.integer "kcal"
|
||||
t.decimal "protein", precision: 10, scale: 2
|
||||
t.decimal "lipid", precision: 10, scale: 2
|
||||
t.decimal "ash", precision: 10, scale: 2
|
||||
t.integer "calcium"
|
||||
t.decimal "carbohydrates", precision: 10, scale: 2
|
||||
t.decimal "cholesterol", precision: 10, scale: 3
|
||||
t.decimal "copper", precision: 10, scale: 3
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.decimal "fiber", precision: 10, scale: 1
|
||||
t.decimal "sugar", precision: 10, scale: 2
|
||||
t.decimal "gram_weight_1", precision: 9, scale: 2
|
||||
t.decimal "gram_weight_2", precision: 9, scale: 2
|
||||
t.string "gram_weight_desc_1"
|
||||
t.string "gram_weight_desc_2"
|
||||
t.text "ingredients"
|
||||
t.decimal "iron", precision: 10, scale: 2
|
||||
t.integer "kcal"
|
||||
t.decimal "lipid", precision: 10, scale: 2
|
||||
t.string "long_description"
|
||||
t.integer "magnesium"
|
||||
t.decimal "manganese", precision: 10, scale: 3
|
||||
t.string "manufacturer"
|
||||
t.string "ndbn", limit: 25
|
||||
t.string "nutrient_unit"
|
||||
t.integer "phosphorus"
|
||||
t.integer "potassium"
|
||||
t.decimal "protein", precision: 10, scale: 2
|
||||
t.string "refuse_description"
|
||||
t.integer "refuse_percent"
|
||||
t.string "scientific_name"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "calcium"
|
||||
t.decimal "iron", precision: 10, scale: 2
|
||||
t.integer "magnesium"
|
||||
t.integer "phosphorus"
|
||||
t.integer "potassium"
|
||||
t.string "short_description"
|
||||
t.integer "sodium"
|
||||
t.decimal "zinc", precision: 10, scale: 2
|
||||
t.decimal "copper", precision: 10, scale: 3
|
||||
t.decimal "manganese", precision: 10, scale: 3
|
||||
t.decimal "vit_c", precision: 10, scale: 1
|
||||
t.decimal "vit_b6", precision: 10, scale: 3
|
||||
t.decimal "vit_b12", precision: 10, scale: 2
|
||||
t.integer "vit_a"
|
||||
t.decimal "vit_e", precision: 10, scale: 2
|
||||
t.decimal "vit_d", precision: 10, scale: 1
|
||||
t.decimal "vit_k", precision: 10, scale: 1
|
||||
t.decimal "cholesterol", precision: 10, scale: 3
|
||||
t.string "source"
|
||||
t.string "manufacturer"
|
||||
t.text "ingredients"
|
||||
t.string "nutrient_unit"
|
||||
t.decimal "sugar", precision: 10, scale: 2
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.integer "vit_a"
|
||||
t.decimal "vit_b12", precision: 10, scale: 2
|
||||
t.decimal "vit_b6", precision: 10, scale: 3
|
||||
t.decimal "vit_c", precision: 10, scale: 1
|
||||
t.decimal "vit_d", precision: 10, scale: 1
|
||||
t.decimal "vit_e", precision: 10, scale: 2
|
||||
t.decimal "vit_k", precision: 10, scale: 1
|
||||
t.decimal "water", precision: 10, scale: 2
|
||||
t.decimal "zinc", precision: 10, scale: 2
|
||||
t.index ["long_description"], name: "index_usda_foods_on_long_description"
|
||||
t.index ["ndbn"], name: "index_usda_foods_on_ndbn"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "username"
|
||||
t.boolean "admin"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.string "email"
|
||||
t.string "full_name"
|
||||
t.string "password_digest"
|
||||
t.boolean "admin"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.string "username"
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user