module ActiveRecord::Enum

Constants

SR_ENUM_KEYWORDS

Public Instance Methods

_define_enum(definitions) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 56
def _define_enum(definitions)
  ActiveRecordOverrides.instance.store_enum_call(self, definitions)
  old_enum(definitions)
end
_define_typed_enum( enum_name, enum_values, strict_mode: false ) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 117
def _define_typed_enum(
  enum_name,
  enum_values,
  strict_mode: false
)
  enum_klass_name = enum_name.to_s.camelize

  # we don't need to use the actual enum value
  typed_enum_values = gen_typed_enum_values(enum_values.map(&:to_s))

  # create dynamic T::Enum definition
  if const_defined?(enum_klass_name)
    # append Enum to avoid conflict
    enum_klass_name = "#{enum_klass_name}Enum"
    if const_defined?(enum_klass_name)
      raise ConflictTypedEnumNameError.new(
        "Unable to define enum class #{enum_klass_name} because
        it's already defined".squish!
      )
    end
  end
  enum_klass = Class.new(T::Enum) do
    enums do
      typed_enum_values.each do |enum_key_name, typed_enum_value|
        const_set(typed_enum_value, new(enum_key_name))
      end
    end
  end
  const_set(enum_klass_name, enum_klass)

  # create t_enum getter to get T::Enum value
  # assuming there shouldn't be any conflict
  typed_enum_getter_name = "typed_#{enum_name}"
  detect_enum_conflict!(enum_name, typed_enum_getter_name)
  define_method(typed_enum_getter_name) do
    T.unsafe(enum_klass).try_deserialize(send(enum_name))
  end

  # override the setter to accept T::Enum values
  enum_setter_name = "#{enum_name}="
  typed_enum_setter_name = "typed_#{enum_name}="
  detect_enum_conflict!(enum_name, typed_enum_setter_name)
  define_method(typed_enum_setter_name) do |value|
    send(enum_setter_name, value&.serialize)
  end

  # add to the config for RBI generation only if it works
  typed_enum_reflections[enum_name.to_s] = SorbetRails::TypedEnumConfig.new(
    strict_mode: strict_mode || false,
    class_name: enum_klass_name,
  )
end
enum(definitions) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 62
def enum(definitions)
  _define_enum(definitions)
  definitions.each do |enum_name, values|
    begin
      # skip irrelevant keywords
      next if SR_ENUM_KEYWORDS.include?(enum_name)
      _define_typed_enum(enum_name, extract_enum_values(values))
    rescue ArgumentError, ConflictTypedEnumNameError, TypeError => ex
      # known errors
      # do nothing if we cannot define t_enum
      puts "warning: #{ex.message}"
    rescue => ex
      # rescue any other kind of error to unblock the application
      # can be disabled in development
      puts "warning: #{ex.message}"
      # raise ex
    end
  end
end
Also aliased as: old_enum
extract_enum_values(enum_def) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 186
def extract_enum_values(enum_def)
  enum_def.is_a?(Array) ? enum_def.map(&:to_sym) : enum_def.keys.map(&:to_sym)
end
gen_typed_enum_values(enum_values) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 171
def gen_typed_enum_values(enum_values)
  Hash[enum_values.map do |val|
    [val, val.to_s.gsub(/[^0-9a-z_]/i, '').camelize]
  end]
end
old_enum(definitions)
Alias for: enum
typed_enum(definitions) click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 83
def typed_enum(definitions)
  enum_names = definitions.keys - SR_ENUM_KEYWORDS

  if enum_names.size != 1
    raise MultipleEnumsDefinedError.new(
      "typed_enum only supports 1 enum defined at a time,
      given #{enum_names.count}: #{enum_names.join(', ')}".squish!
    )
  end

  enum_name = enum_names[0]

  _define_enum(definitions)
  _define_typed_enum(
    T.must(enum_name),
    extract_enum_values(definitions[enum_name]),
    strict_mode: true,
  )
end
typed_enum_reflections() click to toggle source
# File lib/sorbet-rails/rails_mixins/active_record_overrides.rb, line 105
def typed_enum_reflections
  @typed_enum_reflections ||= {}
end