rails: Rails 7.1 - can't define enums for attributes which don't exist in table
Not sure if this is an intended change or not. Pre 7.1, I could define an attr on a model using attribute
and define enum values for it, then use enum helper methods. I’m using this heavily in my current project for i18ns etc, so defining the enum values as an array and manually validating won’t cover all my use cases
Since 7.1, this isn’t possible.
Steps to reproduce
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", github: "rails/rails", branch: "main"
gem "sqlite3"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :posts, force: true do |t|
end
end
class Post < ActiveRecord::Base
attribute :topic
enum topic: %i[sports politics entertainment]
end
class BugTest < Minitest::Test
def test_association_stuff
post = Post.create!
post.assign_attributes(topic: :sports)
assert_equal true, post.sports?
end
end# frozen_string_literal: true
Expected behavior
Post should instantiate correctly and can use enum helper methods
Actual behavior
Error thrown
RuntimeError: Unknown enum attribute 'topic' for Post
System configuration
Rails version: 7.1.1
Ruby version: ruby 3.1.2p20
About this issue
- Original URL
- State: closed
- Created 8 months ago
- Comments: 22 (12 by maintainers)
I am facing this same issue when the model is used in some migration before the enum is introduced for example
Now I get
Yes, that was intentional. See related issue https://github.com/rails/rails/issues/45668 for the discussion of the problem.
cc @byroot
I have issue similar to the one @jasonl has. There is an 3 years old migration in my app, which adds a column to User database table, and it populates it in the loop for each user:
A year later another migration adds new column for storing enum value
and corresponding code to set its values
So now when I reset my schema, I get an error: “
Unknown enum attribute 'another_enum_column' for User
”, because columnanother_enum_column
doesn’t yet exist when older migration calls User model.@byroot Is it possible you might have some kind of solution to resolve this error? I really don’t like the idea to edit old migrations.
We have also encountered this issue, but in a slightly different way. We have a model where we added an enum column to it in a migration created long after the original table. This now creates the problem where we cannot run our migrations for an empty database, as the model defines the enum, but the column backing it doesn’t exist in the DB, and won’t until the migration is run which creates it.
We’ve hacked around it by defining an empty AR model for the table in the migrations which break, but this seems inelegant to say the least.
In several of my project’s models, we define
enum
’s whose values are used to populate acharacter varying
column (we are using Postgres). An exampleenum
is below:Before Rails 7.1, referencing and using
enum
’s likeorder_by_types
above did not raise any errors. With Rails 7.1, tests are now failing with errors like the following:What I am looking for is some guidance on how best to fix this. It appears that we can no longer define
enum
’s inside models without a corresponding database table column.