Class: EmailTemplate::ContentMigrator

Inherits:
BaseService show all
Defined in:
app/services/email_template/content_migrator.rb

Overview

Converts Redactor 3 table-based HTML email content to Redactor 4 Email plugin format
using AI (Gemini via RubyLLM).

The Redactor 4 Email plugin uses semantic HTML that gets converted to email-client
compatible markup via the getEmail() API. Templates are plain HTML with optional
JSON configuration in a block.

Usage:
result = EmailTemplate::ContentMigrator.call(
body: legacy_html_body,
css: legacy_css
)
result[:body_v4] # => converted HTML
result[:css_v4] # => converted CSS (if any)

Constant Summary collapse

DEFAULT_MODEL =
AiModelConstants.id(:content_migration)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from BaseService

#log_debug, #log_error, #log_info, #log_warning, #logger, #options, #tagged_logger

Constructor Details

#initialize(options = {}) ⇒ ContentMigrator

Returns a new instance of ContentMigrator.



23
24
25
26
# File 'app/services/email_template/content_migrator.rb', line 23

def initialize(options = {})
  super
  @model = options[:model].presence || DEFAULT_MODEL
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



21
22
23
# File 'app/services/email_template/content_migrator.rb', line 21

def model
  @model
end

Instance Method Details

#improve_style(body_v4:) ⇒ Hash

Improve styling of existing Redactor 4 content without changing structure or content

Parameters:

  • body_v4 (String)

    Current Redactor 4 HTML content

Returns:

  • (Hash)

    { body_v4: String, success: Boolean, error: String }



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/services/email_template/content_migrator.rb', line 53

def improve_style(body_v4:)
  return { success: false, error: 'No content provided' } if body_v4.blank?

  prompt = build_improve_style_prompt(body_v4)

  # Refresh model registry to ensure latest models are available
  RubyLLM.models.refresh! unless model_available?(model)

  chat = RubyLLM.chat(model: model, provider: :gemini, assume_model_exists: true)
  chat.with_temperature(0.3)
  response = chat.ask(prompt)

  parse_response(response&.content)
rescue StandardError => e
  log_error("Style improvement failed: #{e.message}")
  { success: false, error: "AI style improvement failed: #{e.message}" }
end

#process(body:, css: nil) ⇒ Hash

Convert legacy Redactor 3 content to Redactor 4 Email plugin format

Parameters:

  • body (String)

    Legacy HTML body content

  • css (String) (defaults to: nil)

    Legacy CSS content (optional)

Returns:

  • (Hash)

    { body_v4: String, css_v4: String, success: Boolean, error: String }



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/services/email_template/content_migrator.rb', line 32

def process(body:, css: nil)
  return { success: false, error: 'No body content provided' } if body.blank?

  prompt = build_prompt(body, css)

  # Refresh model registry to ensure latest models are available
  RubyLLM.models.refresh! unless model_available?(model)

  chat = RubyLLM.chat(model: model, provider: :gemini, assume_model_exists: true)
  chat.with_temperature(0.2) # Lower temperature for consistent, deterministic output
  response = chat.ask(prompt)

  parse_response(response&.content)
rescue StandardError => e
  log_error("Content migration failed: #{e.message}")
  { success: false, error: "AI conversion failed: #{e.message}" }
end