/ rails

first_or_create caches the existing scope and applies to the model callbacks

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)