- 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>
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:
- ✅ Understand Block.rb rendering engine (done)
- Identify all active blocks in production
- Categorize blocks:
- Simple HTML passthrough
- Moderate complexity (some conditionals)
- Complex (loops, dynamic content)
- Map each block to Rails view equivalent
- Document {{}} syntax usage patterns
- 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:
-
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 %> -
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 -
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_viewsto Account model - Gradual rollout: test accounts → all dealers
- Monitor performance & error rates
- Easy rollback if issues
Phase 4: Decommission
Remove Block System:
- Delete Block rendering code
- Remove block admin UI
- Drop blocks/block_settings tables
- Delete Block & BlockSetting models
- Remove {{}} template syntax processor
- 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_viewsto 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
-
If too many blocks use advanced features:
- Keep blocks for "legacy mode"
- Migrate new features to Rails views
- Hybrid approach long-term
-
If performance regression:
- Implement aggressive view caching
- Use Redis for cache
- Defer to background jobs
-
If CSR adoption slow:
- Extend timeline
- Provide better training
- Create CSR-facing abstraction layer
Next Steps
-
This Session:
- Query block 112 structure
- Document current {{}} syntax patterns
- Identify block complexity categories
-
Next Session:
- Create first V2 view (appointment form)
- Build presenter/helper structure
- Implement feature flag logic
-
Future:
- Beta testing with select accounts
- Performance optimization
- Full rollout plan
Resources
- Block.rb: 1014 lines, rendering logic in
render()andsubbed_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