2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-10-03 17:21:20 +08:00
discourse/migrations/lib/database/schema/enum_resolver.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

73 lines
1.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
module Migrations::Database::Schema
class EnumResolver
class EnumSourceError < StandardError
end
def initialize(config)
@config = config || {}
end
def resolve
@config.map do |name, entry|
name = name.to_s
values_hash = resolve_values(entry)
datatype = values_hash.values.first.is_a?(String) ? :text : :integer
EnumDefinition.new(name:, values: values_hash, datatype:)
end
end
private
def resolve_values(entry)
if entry.key?(:values)
normalize_values(entry[:values])
elsif entry.key?(:strings)
normalize_strings(entry[:strings])
elsif entry.key?(:source)
fetch_source(entry[:source])
else
raise EnumSourceError, "Enum must define :values, :strings, or :source"
end
end
def normalize_values(values)
case values
when Array
values.each_with_index.to_h { |k, i| [k.to_s, i] }
when Hash
values.transform_keys(&:to_s)
else
raise EnumSourceError, "Invalid :values format: #{values.inspect}"
end
end
def normalize_strings(values)
case values
when Array
values.to_h { |k| [k.to_s, k.to_s] }
when Hash
values.transform_keys(&:to_s).transform_values(&:to_s)
else
raise EnumSourceError, "Invalid :strings format: #{values.inspect}"
end
end
def fetch_source(source_code)
values = eval(source_code, TOPLEVEL_BINDING) # rubocop:disable Security/Eval
case values
when Hash
values.transform_keys(&:to_s)
when Array
values.each_with_index.to_h { |k, i| [k.to_s, i] }
else
raise EnumSourceError, "Eval #{source_code} must return Hash or Array"
end
rescue StandardError => e
raise EnumSourceError, "Failed to evaluate source #{source_code}: #{e.message}"
end
end
end