Class: RubyLLM::Generators::UpgradeGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Includes:
Rails::Generators::Migration, GeneratorHelpers
Defined in:
lib/generators/ruby_llm/upgrade/upgrade_generator.rb

Overview

Upgrades the schema generated by RubyLLM 1.16 to RubyLLM 2.0.

Constant Summary collapse

MODEL_MAPPING_DEFAULTS =
{
  chat: 'Chat',
  message: 'Message',
  model: 'Model',
  tool_call: 'ToolCall'
}.freeze
MODEL_MAPPING_TYPES =
MODEL_MAPPING_DEFAULTS.keys.map(&:to_s).freeze

Constants included from GeneratorHelpers

GeneratorHelpers::APPLICATION_MODEL_TYPES, GeneratorHelpers::DEFAULT_MODEL_NAMES

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GeneratorHelpers

#acts_as_chat_declaration, #acts_as_message_declaration, #chat_controller_class_name, #chat_job_class_name, #create_migration_class_name, #create_namespace_modules, #gem_in_bundle?, #message_controller_class_name, #migration_version, #model_controller_class_name, #model_model_name, #model_resource_name, #model_variable_name, #mysql?, #parse_model_mappings, #postgresql?, #reference_type, #table_exists?, #tailwind_available?, #tool_call_variable_name, #ui_template, #ui_variant, #unprocessable_content_status, #usage_operations_sql, #usage_statuses_sql, #validate_model_mapping!

Class Method Details

.next_migration_number(dirname) ⇒ Object



39
40
41
# File 'lib/generators/ruby_llm/upgrade/upgrade_generator.rb', line 39

def self.next_migration_number(dirname)
  ::ActiveRecord::Generators::Base.next_migration_number(dirname)
end

Instance Method Details

#create_migration_filesObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/generators/ruby_llm/upgrade/upgrade_generator.rb', line 43

def create_migration_files
  validate_cleanup_options
  parse_model_mappings(allowed_types: MODEL_MAPPING_TYPES, defaults: MODEL_MAPPING_DEFAULTS)
  say_status :models, resolved_model_mappings

  if copy_mode? && !options[:phase].in?(%w[backfill finish cleanup])
    template 'ruby_llm_upgrade.rb.tt', 'app/models/concerns/ruby_llm_upgrade.rb'
    template 'upgrade_initializer.rb.tt', 'config/initializers/ruby_llm_upgrade.rb'
  end

  phases = options[:phase] ? [options[:phase]] : %w[prepare backfill finish]
  phases.each do |phase|
    template = phase == 'backfill' ? 'backfill_v2_data' : "#{phase}_v2_upgrade"
    migration = phase == 'backfill' ? 'backfill_ruby_llm_v2_data' : "#{phase}_ruby_llm_v2_upgrade"
    migration_template "#{template}.rb.tt", "db/migrate/#{migration}.rb"
  end
end

#show_next_stepsObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/generators/ruby_llm/upgrade/upgrade_generator.rb', line 61

def show_next_steps
  say_status :success, 'Upgrade prepared!', :green
  if copy_mode?
    say <<~INSTRUCTIONS

      Copy mode retains the legacy tables and a separate chat model reference.
      Install the generated RubyLLMUpgrade concern and initializer in BOTH the
      running 1.16 build and the 2.0 build BEFORE running prepare. Restart
      all affected 1.16 processes so they load the guards and explicit column
      selects. The guards protect whole conversations
      changed by 2.0. Direct SQL, bulk updates/deletes and attachment purges
      bypass these guards; review those application paths before upgrading.

      Rehearse prepare, backfill and finish on a production database copy.
      Run prepare and backfill from the 2.0 build while 1.16 serves traffic.
      Stop affected traffic, workers, scheduled jobs and retries BEFORE finish.
      Finish catches up intervening writes, validates and activates 2.0.
      Then load models and restart the 2.0 application.
      Keep the old model/tool-call classes in the 1.16 build.

      PostgreSQL, MySQL and SQLite support this workflow. Schema changes can
      block writes; SQLite also serializes backfill and app writes.
      Use a direct connection or session-mode pool for copy migrations.
      db:migrate runs ALL pending phases. Stop at the backfill timestamp to
      defer finish, or pause AI before running all three together.

      With all affected processes stopped, use the 2.0 build to run:
        bin/rails ruby_llm:upgrade:rollback  # activates the protected 1.16 view
        bin/rails ruby_llm:upgrade:resume    # reconciles 1.16 writes, activates 2.0

      Finish pending tool calls, approvals and batches before switching.
      Once rollback is no longer needed, run ruby_llm:upgrade:finalize, then
      generate --mode copy --phase cleanup in a later deployment. Keep the
      compatibility files until cleanup succeeds; remove them afterward.

      Pass the same --mode and model mappings to every generator invocation.
      Full guide: https://rubyllm.com/next/upgrading/

    INSTRUCTIONS
    return
  end
  say <<~INSTRUCTIONS

    These migrations expect the schema generated by RubyLLM 1.16. They move
    RubyLLM's model and tool-call records, preserve message content and usage,
    and retain the 1.x message columns until a later cleanup deployment.

    Next steps:
    1. Review the generated migrations
    2. Rehearse them on a recent production snapshot
    3. Stop affected web processes, workers, scheduled jobs, and retries
    4. Run preparation, backfill, and finish before reopening traffic
    5. Run: bin/rails ruby_llm:load_models
    6. Keep only the current declarations in your application models:
       #{chat_model_path}: #{acts_as_chat_declaration}
       #{message_model_path}: #{acts_as_message_declaration}
    7. Remove the 1.x model and tool-call classes, config.model_registry_class,
       and config.use_new_acts_as
    8. Update 1.x API calls using the upgrade guide

    Generate one phase with --phase prepare, backfill, or finish when the
    backfill needs to run outside your deployment's release phase.
    After verifying the upgrade, generate --phase cleanup in a later release.
    Pass the same model mappings to every invocation.

    The migrations are irreversible. Retained columns do not make a code
    rollback safe; recovery requires the previous database and application.

    Full upgrade guide:
       https://rubyllm.com/next/upgrading/

  INSTRUCTIONS
end