CodexBloom - Programming Q&A Platform

best practices for 'ActiveRecord::RecordNotUnique' scenarios when using `find_or_create_by` in a Rails 7 application with unique constraints?

πŸ‘€ Views: 11 πŸ’¬ Answers: 1 πŸ“… Created: 2025-06-05
ruby-on-rails activerecord concurrency ruby

I'm dealing with I'm maintaining legacy code that I've searched everywhere and can't find a clear answer..... I'm working with an scenario with a Rails 7 application where I'm trying to ensure that each user can only create one profile associated with their account. I have a unique index on the `profiles` table for the `user_id` column to enforce this. When I attempt to create a profile using `find_or_create_by`, I sometimes get an `ActiveRecord::RecordNotUnique` behavior, especially under high concurrency, which leads to multiple threads attempting to create the same profile simultaneously. Here's the code I currently have: ```ruby class ProfilesController < ApplicationController def create @profile = Profile.find_or_create_by(user_id: current_user.id) do |profile| profile.name = params[:profile][:name] profile.bio = params[:profile][:bio] end if @profile.persisted? render json: @profile, status: :created else render json: @profile.errors, status: :unprocessable_entity end end end ``` Despite having the unique index in place, I am still seeing the `ActiveRecord::RecordNotUnique` behavior in the logs when multiple requests hit the `create` action at the same time. I've tried wrapping the `find_or_create_by` in a transaction, but it hasn't resolved the scenario. Here’s a snippet of what I attempted: ```ruby ActiveRecord::Base.transaction do @profile = Profile.find_or_create_by(user_id: current_user.id) do |profile| profile.name = params[:profile][:name] profile.bio = params[:profile][:bio] end end ``` Is there a better approach to handle this situation? How can I ensure that I avoid the `ActiveRecord::RecordNotUnique` behavior while still allowing for the creation of profiles in a concurrent environment? Should I consider using locks or some other method? Any guidance on the best practices here would be greatly appreciated. I'm working on a web app that needs to handle this. Any help would be greatly appreciated! Is this even possible? I'm working in a Ubuntu 20.04 environment. Am I approaching this the right way?