问题
I have a stream of data, which contains categories. I want to maintain a Category table which should contain every category I encounter exactly once.
I want to implement a id = Category.upsert(name), which should be atomic (of course), and - if possible - not use stored procedures on the DB side.
回答1:
The upsert gem seems to do just that - I found it while googling to see if "upsert" is a thing.
回答2:
How about this:
class Category < ActiveRecord::Base
...
class << self
def upsert(name)
transaction { self.find_or_create_by(name: name).id }
end
end
end
回答3:
You will have to write an ActiveRecordExtension. Check this out.
The code will look something like this
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)
来源:https://stackoverflow.com/questions/21583648/how-to-implement-upsert-for-postgresql-in-activerecord