How to implement `upsert` for PostgreSQL in ActiveRecord?

I have a data stream that contains categories. I want to save the Category table, which should contain every category I that occurs exactly once.

I want to implement id = Category.upsert(name)which should be atomic (of course) and, if possible, not use stored procedures on the database side.

+3
source share
3 answers

It seems that the gem upsertdoes it this way - I found it during a googling search to see that "upsert" is a thing.

+1
source

How about this:

class Category < ActiveRecord::Base
  ...

  class << self
    def upsert(name)
      transaction { self.find_or_create_by(name: name).id }
    end
  end
end
+1
source

ActiveRecordExtension. .

:

module ActiveRecordExtension
  extend ActiveSupport::Concern

  def upsert(attributes)
    begin
        create(attributes)
    rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation => e
        find_by_primary_key(attributes['primary_key']).
        update(attributes)
    end
  end
end

ActiveRecord::Base.send(:include, ActiveRecordExtension)
-2

All Articles