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
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