I have a model called Event. It looks like this:
class Event < ApplicationRecord
belongs_to :eventable, polymorphic: true
belongs_to :user, inverse_of: :events
validates :event_category, presence: true
enum event_category: {
add_to_library: 0,
change_completion_status: 1,
favorite_game: 2,
new_user: 3,
following: 4
}
end
I was running into errors where users were able to create Events where eventable
didn't match the corresponding type (e.g. GamePurchase
represents a game in a user's library and is what eventable
is supposed to be when the category is add_to_library
), so I added a Postgres check constraint that checks to make sure the event_category and eventable_type match. The problem is that my event factories really don't like this constraint and tries to create records where the event_category
and eventable_type
don't match. Is there a way to fix this?
My factories for Event look like this:
FactoryBot.define do
factory :game_purchase_library_event, class: 'Event', aliases: [:event] do
user
association(:eventable, factory: :game_purchase)
event_category { :add_to_library }
end
factory :game_purchase_completion_event, class: 'Event' do
user
association(:eventable, factory: :game_purchase)
event_category { :change_completion_status }
differences do
# Pick two random values
{ completion_status: GamePurchase.completion_statuses.values.sample(2) }
end
end
factory :favorite_game_event, class: 'Event' do
user
association(:eventable, factory: :favorite_game)
event_category { :favorite_game }
end
factory :new_user_event, class: 'Event' do
user
association(:eventable, factory: :user)
event_category { :new_user }
end
factory :following_event, class: 'Event' do
user
association(:eventable, factory: :relationship)
event_category { :following }
end
end
I'm getting factory_bot lint failures like this:
FactoryBot::InvalidFactoryError: The following factories are invalid:
* game_purchase_library_event+favorite_game - PG::CheckViolation: ERROR: new row for relation "events" violates check constraint "event_category_type_check"
DETAIL: Failing row contains (f9fb682b-8ae6-4d79-b91a-d17c58b4d02c, 29157, 4, 2021-02-28 01:05:27.591942, 2021-02-28 01:05:27.591942, 2, null, GamePurchase).
(ActiveRecord::StatementInvalid)
* game_purchase_library_event+new_user - PG::CheckViolation: ERROR: new row for relation "events" violates check constraint "event_category_type_check"
DETAIL: Failing row contains (a8de4c5c-cdc2-4bdb-9a8f-a09cf1813dac, 13791, 5, 2021-02-28 01:05:27.650202, 2021-02-28 01:05:27.650202, 3, null, GamePurchase).
(ActiveRecord::StatementInvalid)
* game_purchase_library_event+following - PG::CheckViolation: ERROR: new row for relation "events" violates check constraint "event_category_type_check"
DETAIL: Failing row contains (96d11b13-3cdd-44e2-80e5-e4a070ef8ac8, 25781, 6, 2021-02-28 01:05:27.705169, 2021-02-28 01:05:27.705169, 4, null, GamePurchase).
(ActiveRecord::StatementInvalid)
Turns out this was being caused by the automatic generation of enum traits, which is why there were those incompatible traits that were causing the linter to fail. The feature is described here, you can disable it with FactoryBot.automatically_define_enum_traits = false
(I created a factory_bot.rb
file in my initializers directory and disabled it there).