Migration Guide: Version 1.0.0¶
This guide helps you migrate from PromptManager v0.9.x to v1.0.0, which represents the first stable release with a commitment to semantic versioning.
Overview¶
Version 1.0.0 focuses on API stabilization, performance improvements, and enhanced developer experience. While there are some breaking changes, most applications should migrate smoothly.
Major Changes¶
1. Stable Public API¶
- All public APIs are now considered stable
- Semantic versioning is strictly followed from this version forward
- Deprecation warnings will be provided for 6 months before removal
2. Enhanced Storage System¶
- New storage adapter capabilities
- Improved error handling and diagnostics
- Better performance for large prompt libraries
3. Advanced Template Features¶
- Template inheritance system
- Custom directive registration
- Improved ERB integration
Breaking Changes¶
1. Removed Deprecated Methods¶
Methods Removed in v1.0.0¶
# These methods were deprecated in v0.9.x and removed in v1.0.0
# OLD (removed):
prompt.enable_erb = true
prompt.enable_envar = true
# NEW (use during initialization):
prompt = PromptManager::Prompt.new(
id: 'template',
erb_flag: true,
envar_flag: true
)
Migration Steps¶
- Remove usage of deprecated setter methods
- Pass flags during prompt initialization
2. Storage Adapter Method Signatures¶
Updated Method Signatures¶
# OLD (v0.9.x):
def read(prompt_id)
# Simple string return
end
# NEW (v1.0.0):
def read(prompt_id)
# Can return string or PromptData object
end
# NEW: Enhanced read method (optional)
def read_with_metadata(prompt_id)
{
content: "prompt content",
metadata: { author: "user", version: 1 },
last_modified: Time.current
}
end
Migration Steps¶
- No changes required for basic adapters
- Optionally implement
read_with_metadata
for enhanced functionality
3. Configuration Changes¶
Updated Configuration Structure¶
# OLD (v0.9.x):
PromptManager.configure do |config|
config.cache_prompts = true
config.cache_ttl = 300
end
# NEW (v1.0.0):
PromptManager.configure do |config|
config.cache = {
enabled: true,
ttl: 300,
store: :memory, # or :redis, :memcached
options: {}
}
end
Migration Steps¶
- Update cache configuration to use nested structure
- Specify cache store type explicitly
New Features¶
1. Template Inheritance¶
Create reusable template hierarchies:
# layouts/base.txt
<!DOCTYPE html>
<html>
<head>
<title>//yield title</title>
</head>
<body>
<h1>//yield heading</h1>
<div class="content">
//yield content
</div>
</body>
</html>
# email.txt
//extends layouts/base
//section title: Email Notification
//section heading: Important Update
//section content: Your account has been updated.
2. Custom Directive System¶
Register custom processing directives:
PromptManager.configure do |config|
config.register_directive('timestamp') do |format, context|
Time.current.strftime(format || '%Y-%m-%d %H:%M:%S')
end
config.register_directive('user_info') do |user_id, context|
user = User.find(user_id)
"#{user.name} (#{user.email})"
end
end
# Usage in prompts:
# Generated at: //timestamp %B %d, %Y
# User: //user_info [USER_ID]
3. Enhanced Error Information¶
More detailed error messages and context:
begin
prompt.render(incomplete_params)
rescue PromptManager::MissingParametersError => e
puts "Missing parameters:"
e.missing_parameters.each do |param|
puts " - #{param[:name]} (line #{param[:line]})"
end
puts "Suggestions:"
e.suggestions.each { |suggestion| puts " - #{suggestion}" }
end
4. Performance Monitoring¶
Built-in performance tracking:
PromptManager.configure do |config|
config.performance_monitoring = {
enabled: true,
slow_threshold: 0.1, # seconds
callback: ->(metrics) {
Rails.logger.warn "Slow prompt: #{metrics[:prompt_id]} (#{metrics[:duration]}s)"
}
}
end
Database Schema Updates (ActiveRecord Adapter)¶
New Schema for Enhanced Features¶
class UpdatePromptsForV100 < ActiveRecord::Migration[7.0]
def change
# Add versioning support
add_column :prompts, :version_number, :integer, default: 1
add_column :prompts, :parent_version, :integer
# Add template inheritance
add_column :prompts, :extends, :string
add_column :prompts, :template_type, :string, default: 'prompt'
# Add usage tracking
add_column :prompts, :usage_count, :integer, default: 0
add_column :prompts, :last_used_at, :timestamp
# Add performance tracking
add_column :prompts, :avg_render_time, :decimal, precision: 8, scale: 4
add_column :prompts, :last_render_time, :decimal, precision: 8, scale: 4
# Enhanced metadata
change_column :prompts, :metadata, :jsonb # PostgreSQL
# For MySQL: change_column :prompts, :metadata, :json
# New indexes
add_index :prompts, :version_number
add_index :prompts, :template_type
add_index :prompts, :usage_count
add_index :prompts, :last_used_at
add_index :prompts, [:extends, :template_type]
# GIN index for metadata search (PostgreSQL)
add_index :prompts, :metadata, using: :gin
end
def down
remove_column :prompts, :version_number
remove_column :prompts, :parent_version
remove_column :prompts, :extends
remove_column :prompts, :template_type
remove_column :prompts, :usage_count
remove_column :prompts, :last_used_at
remove_column :prompts, :avg_render_time
remove_column :prompts, :last_render_time
end
end
Configuration Migration¶
Full Configuration Example¶
# config/initializers/prompt_manager.rb (v1.0.0)
PromptManager.configure do |config|
# Storage configuration
config.storage = if Rails.env.production?
PromptManager::Storage::ActiveRecordAdapter.new(
model_class: Prompt,
enable_versioning: true,
enable_usage_tracking: true
)
else
PromptManager::Storage::FileSystemAdapter.new(
prompts_dir: Rails.root.join('app', 'prompts'),
enable_hot_reload: Rails.env.development?
)
end
# Caching configuration
config.cache = {
enabled: Rails.env.production?,
ttl: 1.hour,
store: :redis,
options: {
url: ENV['REDIS_URL'],
namespace: 'prompt_manager',
compress: true
}
}
# Template processing
config.templates = {
inheritance_enabled: true,
max_inheritance_depth: 5,
custom_directives: true
}
# Performance monitoring
config.performance_monitoring = {
enabled: Rails.env.production?,
slow_threshold: 0.5,
callback: ->(metrics) {
Rails.logger.info "PromptManager: #{metrics[:prompt_id]} rendered in #{metrics[:duration]}s"
if metrics[:duration] > config.performance_monitoring[:slow_threshold]
SlackNotifier.notify("Slow prompt detected: #{metrics[:prompt_id]}")
end
}
}
# Error handling
config.error_handling = {
raise_on_missing_prompts: Rails.env.development?,
raise_on_missing_parameters: Rails.env.development?,
fallback_handler: ->(error, context) {
Rails.logger.error "PromptManager error: #{error.message}"
Rails.logger.error "Context: #{context.inspect}"
case error
when PromptManager::PromptNotFoundError
"[Prompt temporarily unavailable]"
when PromptManager::MissingParametersError
"[Missing: #{error.missing_parameters.map(&:name).join(', ')}]"
else
"[Content unavailable]"
end
}
}
# Custom directives
config.register_directive('format_currency') do |amount, currency, context|
# Custom currency formatting logic
Money.new(amount.to_f * 100, currency).format
end
config.register_directive('user_avatar') do |user_id, size, context|
user = User.find(user_id)
user.avatar.variant(resize: "#{size}x#{size}").url
end
end
Step-by-Step Migration¶
1. Update Dependencies¶
# Gemfile
gem 'prompt_manager', '~> 1.0.0'
# If using additional features:
gem 'redis-rails' # For Redis caching
gem 'money-rails' # For currency formatting example
2. Run Database Migration¶
rails generate migration UpdatePromptsForV100
# Edit the migration with schema changes above
rails db:migrate
3. Update Configuration¶
Replace your existing configuration with the new structure shown above.
4. Update Custom Storage Adapters¶
class CustomAdapter < PromptManager::Storage::Base
# Add new optional methods for enhanced features
def read_with_metadata(prompt_id)
content = read(prompt_id)
{
content: content,
metadata: get_metadata(prompt_id),
last_modified: get_last_modified(prompt_id)
}
rescue PromptNotFoundError
raise
end
def track_usage(prompt_id, render_time)
# Optional: implement usage tracking
end
def get_versions(prompt_id)
# Optional: implement versioning
[{ version: 1, content: read(prompt_id), created_at: Time.current }]
end
end
5. Update Application Code¶
# OLD (v0.9.x):
class EmailService
def send_welcome_email(user)
prompt = PromptManager::Prompt.new(id: 'welcome_email')
content = prompt.render(user: user)
# Send email
end
end
# NEW (v1.0.0) - with error handling:
class EmailService
def send_welcome_email(user)
begin
prompt = PromptManager::Prompt.new(id: 'welcome_email')
content = prompt.render(user: user)
EmailMailer.welcome(user, content).deliver_later
rescue PromptManager::PromptNotFoundError
Rails.logger.error "Welcome email template not found"
EmailMailer.fallback_welcome(user).deliver_later
rescue PromptManager::MissingParametersError => e
Rails.logger.error "Missing email parameters: #{e.missing_parameters.join(', ')}"
# Handle gracefully or re-raise
end
end
end
6. Migrate to Template Inheritance¶
Convert related prompts to use inheritance:
# Before: Separate files with duplicated structure
# welcome_email.txt, reset_password_email.txt, etc.
# After: Base template + specific content
# templates/email_base.txt
Subject: [SUBJECT]
Dear [USER_NAME],
[CONTENT]
Best regards,
The [COMPANY_NAME] Team
---
This email was sent to [USER_EMAIL].
To unsubscribe, visit [UNSUBSCRIBE_URL]
# welcome_email.txt
//extends templates/email_base
//section subject: Welcome to [COMPANY_NAME]!
//section content: Thank you for joining us. We're excited to have you aboard!
# reset_password_email.txt
//extends templates/email_base
//section subject: Password Reset Request
//section content: Click here to reset your password: [RESET_URL]
Testing Migration¶
Automated Migration Test¶
# test/migration_test.rb
require 'test_helper'
class V100MigrationTest < ActiveSupport::TestCase
def setup
# Setup test data
end
test "basic prompt rendering still works" do
prompt = PromptManager::Prompt.new(id: 'test_prompt')
result = prompt.render(name: 'Test')
assert_equal 'Hello Test!', result
end
test "template inheritance works" do
prompt = PromptManager::Prompt.new(id: 'inherited_prompt')
result = prompt.render(title: 'Test Page', content: 'Test content')
assert_includes result, 'Test Page'
assert_includes result, 'Test content'
end
test "custom directives work" do
prompt = PromptManager::Prompt.new(id: 'directive_prompt')
result = prompt.render
assert_match /\d{4}-\d{2}-\d{2}/, result # Should include timestamp
end
test "error handling provides detailed information" do
prompt = PromptManager::Prompt.new(id: 'param_prompt')
error = assert_raises(PromptManager::MissingParametersError) do
prompt.render # Missing required parameters
end
assert error.missing_parameters.any?
assert error.suggestions.any?
end
end
Performance Verification¶
# test/performance_test.rb
require 'test_helper'
require 'benchmark'
class V100PerformanceTest < ActiveSupport::TestCase
test "rendering performance is acceptable" do
prompt = PromptManager::Prompt.new(id: 'complex_prompt')
params = { user: create_test_user, items: create_test_items(100) }
time = Benchmark.measure do
100.times { prompt.render(params) }
end
# Should render 100 complex prompts in under 1 second
assert time.real < 1.0, "Rendering too slow: #{time.real}s"
end
end
Rollback Procedures¶
Quick Rollback¶
# 1. Update Gemfile
gem 'prompt_manager', '~> 0.9.0'
# 2. Bundle install
bundle install
# 3. Rollback database
rails db:rollback STEP=1
# 4. Restart application
Configuration Rollback¶
Keep a backup of your v0.9.x configuration:
# config/initializers/prompt_manager_v09_backup.rb
PromptManager.configure do |config|
config.storage = PromptManager::Storage::FileSystemAdapter.new(
prompts_dir: Rails.root.join('app', 'prompts')
)
config.cache_prompts = true
config.cache_ttl = 1800
end
Validation Checklist¶
- Dependencies Updated: Gemfile shows v1.0.0
- Database Migrated: New columns and indexes created
- Configuration Updated: New configuration structure in use
- Custom Adapters Updated: Enhanced methods implemented (if applicable)
- Template Inheritance: Converted applicable prompts to use inheritance
- Error Handling: Updated to use new error information
- Tests Updated: All tests pass with new version
- Performance Verified: Rendering performance is acceptable
- Documentation Updated: Internal documentation reflects v1.0.0 features
Getting Support¶
- Documentation: https://madbomber.github.io/prompt_manager
- GitHub Issues: https://github.com/MadBomber/prompt_manager/issues
- Community Forum: https://github.com/MadBomber/prompt_manager/discussions
- Migration Support: Tag issues with
migration-v1.0.0
Post-Migration Optimization¶
1. Enable New Features Gradually¶
Start with basic v1.0.0 functionality, then gradually enable: - Template inheritance - Custom directives - Performance monitoring - Advanced caching
2. Monitor Performance¶
Use the new performance monitoring to identify optimization opportunities:
# Check slow prompts
PromptManager.slow_prompts(threshold: 0.1).each do |prompt_data|
puts "#{prompt_data[:id]}: #{prompt_data[:avg_time]}s average"
end
3. Optimize Storage¶
Consider upgrading storage adapters for better performance: - Use Redis adapter for high-frequency prompts - Enable database connection pooling - Implement read replicas for heavy read workloads
Congratulations! You've successfully migrated to PromptManager v1.0.0. This stable release provides a solid foundation for scaling your prompt management needs.