ruby-on-railsenumsrails-activerecord

Enum, default value reseted to nil on save


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?


Solution

  • 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