Skip to content

Commit 4bd3c78

Browse files
committed
fix: handle duplicate InvitationLogEntry on retry
Second attempt at fixing the "Member has already been taken" validation error when re-sending workshop invitations. Problem: The previous fix (PR #2556) used find_or_initialize_by with the status included in the query. However, the InvitationLogEntry uniqueness constraint only validates (member_id, invitation_type, invitation_id), NOT status. This means: - A member can have ONE success entry AND ONE failure entry for the same invitation - find_or_initialize_by(member, invitation, :success) would return a persisted entry with status=:failed if one existed, causing the wrong status to be used - Or if building a new entry with status=:success when status=:failed already existed, the uniqueness validation would fail Fix: 1. Split the check: first find any existing entry by (member, invitation), ignoring status 2. If found, return it (either success or failure) 3. Only if no entry exists, create a new one with the specified status Additionally, add autosave: false to the has_many :entries association to prevent Rails from attempting to autosave unpersisted entries when fail_batch is called, which was causing "Validation failed: Entries is invalid" errors. Changes: - app/services/invitation_logger.rb: Separate find_or_build_entry logic - app/models/invitation_log.rb: Add autosave: false to entries association Tests: - All 41 existing tests pass - Retry behavior tests verify no duplicate entries are created
1 parent cbf3d60 commit 4bd3c78

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

app/models/invitation_log.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class InvitationLog < ApplicationRecord
66
belongs_to :loggable, polymorphic: true
77
belongs_to :initiator, class_name: 'Member', optional: true
88
belongs_to :chapter, optional: true
9-
has_many :entries, class_name: 'InvitationLogEntry', dependent: :destroy
9+
has_many :entries, class_name: 'InvitationLogEntry', dependent: :destroy, autosave: false
1010

1111
before_create :set_expires_at
1212

app/services/invitation_logger.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,13 @@ def fail_batch(error)
7878
private
7979

8080
def find_or_build_entry(member, invitation, status)
81-
@log.entries.find_or_initialize_by(
82-
member:,
83-
invitation:,
84-
status:
81+
existing_entry = @log.entries.find_by(member: member, invitation: invitation)
82+
return existing_entry if existing_entry
83+
84+
@log.entries.new(
85+
member: member,
86+
invitation: invitation,
87+
status: status
8588
)
8689
end
8790

0 commit comments

Comments
 (0)