2014-02-05 37 views
3

我有一个数据流,其中包含类别。我想维护一个类别表,它应该包含我遇到的每个类别一次。如何在ActiveRecord中为PostgreSQL实现'upsert`?

我想实现一个id = Category.upsert(name),它应该是原子的(当然),并且 - 如果可能的话 - 不要在DB端使用存储过程。

回答

1

The upsert gem seems to do just that - 我发现它时,谷歌搜索是否“upsert”是一件事。

+0

看起来很有趣,但它使用存储过程,而它似乎并没有返回ID /物件(我需要...)。 –

1

如何:

class Category < ActiveRecord::Base 
    ... 

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

不错,但据我了解 - 它有两次往返数据库......你知道一个方法来做一次往返吗? –

+2

你是对的,它的确如此,但据我所知,没有存储过程的人不能做得更好。 – lacrosse

-2

你必须写一个ActiveRecordExtension。检查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) 
+0

这个解决方案几乎不是原子的 - 它甚至不做两次往返 - 它有三个... –

相关问题