claude-os/BLOCKS_DEPRECATION_STRATEGY.md
Bob Roberts 07afb1b7ba Add Block deprecation strategy and Tuffy Appointment Form case study
- BLOCKS_DEPRECATION_STRATEGY.md: Comprehensive 4-phase migration plan from Block system to Rails views
  - Architecture analysis of Block.rb rendering engine
  - 7 pain points for deprecation
  - Detailed implementation steps for each phase
  - Risk mitigation strategies
  - Benefits comparison table

- BLOCK_CASE_STUDY_TUFFY_APPOINTMENT_FORM.md: Deep analysis of Block 122 (Tuffy Appointment Form)
  - Real production block: 43KB, ~1,150 lines, enterprise-grade form
  - Complexity metrics and comparison
  - Complete decomposition strategy into Rails components
  - Presenter class design
  - 4-step form partials with code examples
  - Service layer architecture
  - External JavaScript extraction
  - 8-week implementation timeline
  - Risk assessment and testing strategy

This case study provides the blueprint for migrating all 100+ form blocks in PISTN.
If Block 122 can be successfully migrated, all blocks can be migrated.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 19:39:19 -05:00

8.4 KiB

Block System Deprecation Strategy

Status: Research & Planning Phase Date: 2025-10-24 Purpose: Plan migration from custom Block templating engine to standard Rails views


Current Block System Architecture

What Are Blocks?

Blocks are PISTN's custom templating layer that allows CSRs to modify dealer-specific HTML/CSS/JS without code changes.

Core Components:

  • Block.rb (1014 lines) - Hierarchical rendering engine
  • BlockSetting.rb - Configuration & image handling
  • blocks.js - Frontend behaviors
  • Admin UI - Block editor interface

How Blocks Work

1. Hierarchical Structure (acts_as_tree)

# Parent-child relationship with roles
parent_block
  ├── child_block (role: "header")
  ├── child_block (role: "content")
  └── child_block (role: "footer")

2. Template Substitution ({{...}} syntax)

<!-- Variable substitution -->
<h1>{{account.name}}</h1>

<!-- Conditional logic -->
{{if account.has_appointments?}}
  <div>{{yield.appointments}}</div>
{{/if}}

<!-- Ternary -->
{{account.is_active? ? 'Open' : 'Closed'}}

<!-- Loops -->
{{yield.services.each do |service|}}
  <div>{{service.name}}</div>
{{/yield.services.each}}

3. Whitelist Security

# Only whitelisted methods can be called
WHITELIST = {
  'account' => %w(name phone_number services ...),
  'block' => %w(image_url ...),
  'ANY' => %w(present? blank? to_s zero?)
}

4. Account-Specific Content

  • Universal blocks: account_id = NULL
  • Account-specific: account_id = specific_account
  • Group inheritance: Accounts inherit parent group's blocks
  • Priority: Account-specific > Group > Universal

Why Deprecate Blocks?

Pain Points

Developer Experience

  • ❌ 1000+ lines of state machine rendering logic
  • ❌ Three languages in one file: HTML + Handlebars + Ruby
  • ❌ No IDE support (syntax highlighting, autocomplete)
  • ❌ Difficult to debug template logic

Maintenance & Testing

  • ❌ Complex caching logic (cache invalidation bugs)
  • ❌ Hard to unit test (requires full render context)
  • ❌ N+1 query potential in template evaluation
  • ❌ Security audits need constant whitelist review

Performance

  • ❌ Interpretation layer (regex parsing, method lookup)
  • ❌ Heavy context object passing
  • ❌ Caching complexity adds overhead

User Experience (CSRs)

  • ❌ Admin UI for block editing is clunky
  • ❌ Learning curve (handlebars syntax)
  • ❌ No real-time preview
  • ❌ Error messages unhelpful

Architecture

  • ⚠️ Views Still Required: Rails views exist anyway (blocks are a layer on top)
  • ⚠️ Duplication: Both block template + Rails view exist
  • ⚠️ Migration Complexity: Must maintain dual rendering for transition

Migration Strategy

Phase 1: Analysis & Mapping (Current)

Tasks:

  1. ✅ Understand Block.rb rendering engine (done)
  2. Identify all active blocks in production
  3. Categorize blocks:
    • Simple HTML passthrough
    • Moderate complexity (some conditionals)
    • Complex (loops, dynamic content)
  4. Map each block to Rails view equivalent
  5. Document {{}} syntax usage patterns
  6. Identify which blocks use advanced features

Block 112 Case Study (Appointment Form):

TODO: Query production database
- Block structure
- {{}} syntax patterns
- Block settings used
- Conditional rendering logic
- Child blocks/context

Phase 2: Create Replacement Views

For Each Block Type:

  1. Create Rails Partial/View

    <!-- app/views/account_specific/_appointment_form.html.erb -->
    <%= form_for @appointment do |f| %>
      <%= f.text_field :date %>
      <%= f.text_field :time %>
      <%= f.submit %>
    <% end %>
    
  2. Move Whitelist Logic to Presenter

    # app/presenters/account_presenter.rb
    class AccountPresenter
      def initialize(account)
        @account = account
      end
    
      def appointment_link
        # Only include if account has appointments enabled
        link_to "Book Appointment", appointment_path if @account.appointments_enabled?
      end
    end
    
  3. Use Rails Helpers

    • Form helpers (form_for, form_with)
    • Link helpers (link_to, button_to)
    • Conditional helpers (if, unless)
    • Loop helpers (each, collect)

Phase 3: Gradual Migration

Feature Flag Approach:

# config/initializers/feature_flags.rb
FEATURE_FLAGS = {
  use_rails_views: false  # Start as false, enable per account
}

# In views/controllers
if account.use_rails_views?
  render :appointment_form_v2
else
  render_block(112)  # Old block system
end

Per-Account Migration:

  • Add boolean use_rails_views to Account model
  • Gradual rollout: test accounts → all dealers
  • Monitor performance & error rates
  • Easy rollback if issues

Phase 4: Decommission

Remove Block System:

  1. Delete Block rendering code
  2. Remove block admin UI
  3. Drop blocks/block_settings tables
  4. Delete Block & BlockSetting models
  5. Remove {{}} template syntax processor
  6. Clean up views that use render_block()

Implementation Steps

Step 1: Research & Planning

  • Query block 112 from production
  • Document all {{}} patterns used
  • Identify all active blocks
  • Categorize by complexity
  • Create mapping document

Step 2: Build Replacement Views

  • Create V2 views in app/views/account_specific/
  • Create presenters in app/presenters/
  • Move authorization logic to policies
  • Create helpers for common patterns

Step 3: Feature Flag & Testing

  • Add use_rails_views to Account
  • Implement feature flag logic
  • Test with sample accounts
  • Performance testing
  • Error monitoring

Step 4: Rollout

  • Internal team testing
  • Beta test with select dealers
  • Gradual rollout to all accounts
  • Monitor metrics
  • Collect feedback

Step 5: Cleanup

  • Remove block system code
  • Delete admin UI
  • Drop database tables
  • Update documentation

Benefits After Migration

Aspect Before (Blocks) After (Rails Views)
Code Custom 1000+ line engine Standard Rails patterns
Language HTML + Handlebars + Ruby ERB only
Testing Integration tests required Standard view tests
IDE No support Full syntax highlighting
Performance Interpretation layer Direct rendering
Security Massive whitelist Rails authorization
Debugging Context tracing Standard stack traces
CSR UX Block admin UI Standard Rails admin (ActiveAdmin, etc)
Onboarding Learn handlebars syntax Standard Rails knowledge

Risk Mitigation

Risks

Performance: Template rendering much slower?

  • Mitigation: Rails view caching (fragment caching, etags)
  • Testing: Benchmark before/after

Breaking Changes: Block customizations that can't translate?

  • Mitigation: Identify edge cases in Phase 1
  • Fallback: Keep Block system for complex accounts

CSR Disruption: CSRs dependent on block editor?

  • Mitigation: Train on new Rails admin interface
  • Timeline: Gradual rollout (6+ months)

Database Migration: Data loss from dropping tables?

  • Mitigation: Archive block data before deletion
  • Backup: Keep block definitions in version control

Contingency Plans

  1. If too many blocks use advanced features:

    • Keep blocks for "legacy mode"
    • Migrate new features to Rails views
    • Hybrid approach long-term
  2. If performance regression:

    • Implement aggressive view caching
    • Use Redis for cache
    • Defer to background jobs
  3. If CSR adoption slow:

    • Extend timeline
    • Provide better training
    • Create CSR-facing abstraction layer

Next Steps

  1. This Session:

    • Query block 112 structure
    • Document current {{}} syntax patterns
    • Identify block complexity categories
  2. Next Session:

    • Create first V2 view (appointment form)
    • Build presenter/helper structure
    • Implement feature flag logic
  3. Future:

    • Beta testing with select accounts
    • Performance optimization
    • Full rollout plan

Resources

  • Block.rb: 1014 lines, rendering logic in render() and subbed_content()
  • BlockSetting.rb: Configuration and image handling
  • BLOCKS_SYSTEM_GUIDE.md: Comprehensive architecture documentation
  • Database: blocks, block_settings, accounts tables

Status: Ready for Phase 1 Analysis Owner: Engineering Team Timeline: 3-6 months estimated