In a RoR 7.1.3 application using PostgreSQL, I've a enum defined as:
create_enum :foo_states, %i[active inactive]
create_table :foo do |t|
t.enum :state, enum_type: :foo_states, default: :active, null: false
end
class Foo < ApplicationRecord
enum :state, %i[active inactive], default: :active, validate: true
end
When I instanciate a new object it works fine:
Foo.new
=> #<Foo state: "active">
Foo.create(state: :bar).errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=state, type=inclusion, ...
But when saving records it does not persist its state
:
foo = Foo.new
=> #<Foo state: "active">
foo.save
=> #<Foo state: nil>
# same on .create
Foo.create
=> #<Foo state: nil>
Is this the expected behaviour? If so, how am I using this feature incorrectly?
You create enum in the database layer with active
and inactive
strings as possible values
But when you write in the model
enum :state, %i[active inactive], default: :active, validate: true
it means you will try to save 0
for active
and 1
for inactive
(index as integer)
Instead of this define enum in the model as hash such way
enum :state, { active: 'active', inactive: 'inactive' }, default: :active, validate: true
From the docs:
Declare an enum attribute where the values map to integers in the database, but can be queried by name
class Conversation < ActiveRecord::Base enum :status, [ :active, :archived ] end # conversation.update! status: 0 conversation.active!
Finally it’s also possible to use a string column to persist the enumerated value
class Conversation < ActiveRecord::Base enum :status, active: "active", archived: "archived" end