RabbitMQ 메시지 처리 시 Group 레코드 생성 과정에서 Creator(User) 레코드가 존재하지 않아 발생하는 유효성 검사 오류는 흔한 문제입니다. 초기 구현에서는 retrieve_creator 메서드가 nil을 반환하여 Group 생성에 실패할 수 있습니다.
문제 상황: Creator(User) 부재 시 Group 생성 실패
ruby
class GroupCreateEventProcessor
# ...
def work(message)
parsed_message = JSON.parse(message)
creator = retrieve_creator(external_id: parsed_message[:external_creator_id])
# creator가 nil이면 Group.create에서 creator_id: nil이 되어 유효성 오류 발생
group = Group.create(
external_id: parsed_message[:external_id],
name: parsed_message[:name],
creator_id: creator.id # creator가 nil일 경우 에러
)
# ...
end
private
def retrieve_creator(external_id:)
User.find_by(external_id:) # User가 없으면 nil 반환
end
end
User 모델의 email 필드가 NOT NULL 제약 조건과 presence: true 유효성 검사를 가지고 있어, 단순히 User.create를 시도하면 email 누락으로 실패합니다.
해결책 1: find_or_create_by 블록 구문 활용
누락된 User 레코드를 자동으로 생성하려면 find_or_create_by 메서드를 사용하고, User 모델의 유효성 검사를 통과하기 위해 email과 같은 필수 속성을 블록 내에서 설정해야 합니다.
ruby
class GroupCreateEventProcessor
# ...
private
def retrieve_creator(external_id:, user_email:)
User.find_or_create_by(external_id:) do |user|
user.email = user_email # 누락된 User 생성 시 email 설정
end
end
end
이 방식은 필요한 레코드가 없을 경우 자체적으로 복구하는 흐름을 제공하여, 새로운 Group 생성에 필요한 User 레코드를 보장합니다.
해결책 2: create_with 구문 활용
`ActiveRecord::QueryMethods
create_with는 레코드 생성 시 사용될 속성을 미리 설정하는 기능을 제공합니다. 이를 find_or_create_by`와 함께 사용하여 코드를 더욱 간결하게 만들 수 있습니다.
ruby
def retrieve_creator(external_id:, user_email:)
User
.create_with(email: user_email) # 생성 시 email 속성 사전 설정
.find_or_create_by(external_id:) # external_id로 조회 또는 생성
end
이 방식은 external_id로 레코드를 조회하는 특수성을 유지하면서, 레코드 생성 시 RabbitMQ 메시지에서 오는 user_email을 사용하도록 지시합니다. create_with는 블록 구문에 비해 단순한 속성 설정에 더 깔끔한 문법을 제공하지만, 복잡한 로직을 통해 값을 생성해야 할 경우에는 블록 구문이 더 유연합니다.