skillby rubys
compare-erb-js
Compare ERB and JavaScript template outputs for the offline scoring SPA. Use when working on ERB-to-JS conversion, debugging template parity issues, or verifying that changes to scoring views work correctly in both ERB and SPA modes.
Installs: 0
Used in: 1 repos
Updated: 1d ago
$
npx ai-builder add skill rubys/compare-erb-jsInstalls to .claude/skills/compare-erb-js/
# Compare ERB vs JavaScript Template Output
Use `scripts/render_erb_and_js.rb` to verify that ERB templates and their JavaScript-converted equivalents produce matching output. This is essential for the offline scoring SPA which uses auto-converted ERB templates.
## Basic Usage
```bash
# Compare heat list
bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83
# Compare individual heat
bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83 1
# With style parameter
bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83 1 radio
```
Or using environment variable:
```bash
RAILS_APP_DB=2025-barcelona-november bundle exec ruby scripts/render_erb_and_js.rb 83 1
```
## What It Does
1. Renders the ERB template via Rails routing (extracts `<main>` content)
2. Fetches converted JavaScript templates from `/templates/scoring.js`
3. Fetches normalized data from `/scores/:judge/heats/data`
4. Hydrates the data using `heat_hydrator.js` (for individual heats)
5. Renders using the JavaScript template
6. Compares row counts and saves both outputs for diff analysis
## Output Files
All files are saved to `/tmp/` for analysis:
- `/tmp/erb_rendered.html` - ERB template output (main content only)
- `/tmp/js_rendered.html` - JavaScript template output
- `/tmp/scoring_templates.js` - Converted templates from `/templates/scoring.js`
- `/tmp/heats_data.json` - Raw normalized data from server
- `/tmp/js_template_data.json` - Hydrated data passed to JS template
## Analyzing Differences
```bash
# Quick diff
diff /tmp/erb_rendered.html /tmp/js_rendered.html
# Side-by-side comparison
diff -y /tmp/erb_rendered.html /tmp/js_rendered.html | less
# Compare specific attributes
diff <(grep -o 'href="[^"]*"' /tmp/erb_rendered.html | sort) \
<(grep -o 'href="[^"]*"' /tmp/js_rendered.html | sort)
```
## Common Differences
Some differences are expected due to ERB-to-JS conversion limitations:
- **HTML entity encoding**: ERB uses `"` while JS uses `"`
- **link_to blocks**: Block form of `link_to` may render differently
- **Whitespace**: Minor whitespace differences are normal
## Architecture
This tool supports the "Server computes, hydration joins, templates filter" principle:
- **Server**: Computes derived values and paths (respects RAILS_APP_SCOPE)
- **Hydration**: `heat_hydrator.js` joins normalized data by resolving IDs
- **Templates**: ERB and JS templates filter/format data identically
## Key Source Files
### Server-side (Rails)
- `app/controllers/scores_controller.rb`
- `heats_data` action: Returns normalized JSON data for SPA
- `heat` action: Sets instance variables for ERB templates
- Computes `paths:` hash with server-computed URLs
- `app/controllers/templates_controller.rb`
- `scoring` action: Converts ERB templates to JavaScript on-the-fly
- Defines path helper stubs for JS templates
- Uses `ErbPrismConverter` for conversion
- `lib/erb_prism_converter.rb`
- Converts ERB templates to JavaScript functions using Ruby's Prism parser
- Handles Ruby-to-JS translation (loops, conditionals, method calls)
### Client-side (JavaScript)
- `app/javascript/lib/heat_hydrator.js`
- `buildLookupTables()`: Creates Maps for O(1) entity lookup
- `hydrateHeat()`: Resolves IDs to full objects
- `buildHeatTemplateData()`: Prepares complete data for templates
- `app/javascript/controllers/heat_app_controller.js`
- Main Stimulus controller for the offline scoring SPA
- Loads templates and data, handles navigation
- Manages offline/online state transitions
### ERB Templates (source of truth)
- `app/views/scores/heat.html.erb` - Main heat view
- `app/views/scores/heatlist.html.erb` - Heat list view
- `app/views/scores/_heat_header.html.erb` - Heat header partial
- `app/views/scores/_info_box.html.erb` - Info box with feedback errors
- `app/views/scores/_navigation_footer.html.erb` - Prev/next navigation
- `app/views/scores/_table_heat.html.erb` - Standard heat table
- `app/views/scores/_rank_heat.html.erb` - Finals ranking view
- `app/views/scores/_solo_heat.html.erb` - Solo heat view
- `app/views/scores/_cards_heat.html.erb` - Card-based scoring view
### Scripts
- `scripts/render_erb_and_js.rb` - This comparison tool
- `scripts/hydrate_heats.mjs` - Node.js script for hydrating data (used by comparison tool)Quick Install
$
npx ai-builder add skill rubys/compare-erb-jsDetails
- Type
- skill
- Author
- rubys
- Slug
- rubys/compare-erb-js
- Created
- 4d ago