mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Use the database type to deserialize enum
This fixes incorrect assumptions made by e991c7b
that we can assume the
DB is already casting the value for us. The enum type needs additional
information to perform casting, and needs a subtype.
I've opted not to call `super` in `cast`, as we have a known set of
types which we accept there, and the subtype likely doesn't accept them
(symbol -> integer doesn't make sense)
Close #23190
This commit is contained in:
parent
8de32bb252
commit
67c1719012
4 changed files with 19 additions and 4 deletions
|
@ -105,9 +105,10 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
class EnumType < Type::Value # :nodoc:
|
||||
def initialize(name, mapping)
|
||||
def initialize(name, mapping, subtype)
|
||||
@name = name
|
||||
@mapping = mapping
|
||||
@subtype = subtype
|
||||
end
|
||||
|
||||
def cast(value)
|
||||
|
@ -124,7 +125,7 @@ module ActiveRecord
|
|||
|
||||
def deserialize(value)
|
||||
return if value.nil?
|
||||
mapping.key(value)
|
||||
mapping.key(subtype.deserialize(value))
|
||||
end
|
||||
|
||||
def serialize(value)
|
||||
|
@ -139,7 +140,7 @@ module ActiveRecord
|
|||
|
||||
protected
|
||||
|
||||
attr_reader :name, :mapping
|
||||
attr_reader :name, :mapping, :subtype
|
||||
end
|
||||
|
||||
def enum(definitions)
|
||||
|
@ -158,7 +159,9 @@ module ActiveRecord
|
|||
detect_enum_conflict!(name, name)
|
||||
detect_enum_conflict!(name, "#{name}=")
|
||||
|
||||
attribute name, EnumType.new(name, enum_values)
|
||||
decorate_attribute_type(name, :enum) do |subtype|
|
||||
EnumType.new(name, enum_values, subtype)
|
||||
end
|
||||
|
||||
_enum_methods_module.module_eval do
|
||||
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
|
||||
|
|
|
@ -411,4 +411,14 @@ class EnumTest < ActiveRecord::TestCase
|
|||
assert book.proposed?, "expected fixture to default to proposed status"
|
||||
assert book.in_english?, "expected fixture to default to english language"
|
||||
end
|
||||
|
||||
test "uses default value from database on initialization" do
|
||||
book = Book.new
|
||||
assert book.proposed?
|
||||
end
|
||||
|
||||
test "uses default value from database on initialization when using custom mapping" do
|
||||
book = Book.new
|
||||
assert book.hard?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,6 +14,7 @@ class Book < ActiveRecord::Base
|
|||
enum author_visibility: [:visible, :invisible], _prefix: true
|
||||
enum illustrator_visibility: [:visible, :invisible], _prefix: true
|
||||
enum font_size: [:small, :medium, :large], _prefix: :with, _suffix: true
|
||||
enum cover: { hard: 'hard', soft: 'soft' }
|
||||
|
||||
def published!
|
||||
super
|
||||
|
|
|
@ -104,6 +104,7 @@ ActiveRecord::Schema.define do
|
|||
t.column :author_visibility, :integer, default: 0
|
||||
t.column :illustrator_visibility, :integer, default: 0
|
||||
t.column :font_size, :integer, default: 0
|
||||
t.column :cover, :string, default: 'hard'
|
||||
end
|
||||
|
||||
create_table :booleans, force: true do |t|
|
||||
|
|
Loading…
Reference in a new issue