We were debugging one issue in our application which was caching the scope we had in where clause for first_or_create in model callbacks - and found one interesting issue -

Theconditions in the where clause were cached in after_create callback if we use where().first_or_create, please check example below -

Example:

Contact.where(first_name: 'Kiprosh').first_or_create

Contact Model:
after_create :sanitize

def sanitize
   Contact.where(creator_id: 123).solr_index
end

This should fire Contact.where(creator_id: 123) but

instead fires Contact.where(first_name: 'Kiprosh', creator_id: 123)

On further checking for this issue and reading blogs we found reason for the issue is its implementation, please check the code below for understanding the issue -

scope = @user.contacts.where(creator_id: @sub_user.id)
scope.first || scope.create or scope.first || scope.scoping { Contact.create }

Rails Source Code

References -

WORKAROUND

  • Contact.where().first_or_initialize.save or
  • Contact.where(params).first || Contact.create(params)