---
name: compare-erb-js-c19b9eebb9f8
description: 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.
---

# 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 `&quot;` 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)


---
Source attribution: rubys
Original project: https://github.com/rubys/showcase/blob/168b37f485f8437d7305b6aba0a55a25abbfd7ae/.claude/skills/compare-erb-js/skill.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Dave AI.

## Upstream license notice

Copyright (c) 2022 Sam Ruby

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



# Dave AI resource metadata

Creator / publisher: rubys
Original project: https://github.com/rubys/showcase/blob/168b37f485f8437d7305b6aba0a55a25abbfd7ae/.claude/skills/compare-erb-js/skill.md
Attribution basis: Source repository record

Fields of work: Development & Engineering, Product Management
Roles: Backend Developer, Frontend Developer, Product Manager
Specialties: Backend
Tools: Rails
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: 0c6a4a8cc80c48b02238d5bfb899318eeaedead329c0d743b0e7ef95d9a97656
