2011-01-14 17 views

Odpowiedz

13

Model.find_or_initialize Prawdopodobnie robi to, co chcesz. Możesz połączyć go z save lub update_attributes, jeśli ma to sens.

Więcej informacji pod numerem Rails Guides.

+3

zobacz komentarz na temat odpowiedzi na makaron – tybro0103

+1

Czy ktokolwiek to widział, generuje upsert? Przewodnik po szynach wskazuje, że nowy obiekt nie będzie jeszcze przechowywany w DB, więc nie widzę, jak to jest prawdziwy pakiet DB. Oznacza to, że nie będzie działać niezawodnie w środowisku wielowątkowym. – stuckj

+2

To rozwiązanie ma problemy z współbieżnością. Nie powiedzie się, jeśli inny wątek aktualizuje tabelę między 'find_or_initialize' i' save'. –

3

Istnieje również Model.find_or_create

+6

To nie robi upsert. Wykonuje selekcję, a następnie (opcjonalnie) wstawkę. Wpływasz na ten sam efekt w świecie z pojedynczym gwintem, w świecie wielowątkowym, ale potrzebujesz go, by uzyskać rzeczywisty efekt. – tybro0103

-1

napisałem na blogu jak możemy to osiągnąć. Sprawdź to here.

Musisz napisać aktywne rozszerzenie rekordu. Będzie wyglądać mniej więcej tak.

module ActiveRecordExtension 
    extend ActiveSupport::Concern 

    def self.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) 
+3

Nie jest fanem używania błędów do sterowania spodziewanym przepływem logicznym, zwłaszcza gdy można przewidzieć, kiedy wystąpi ten błąd. – kmanzana

+0

dobry punkt @kmanzana. trochę za hackish dla mnie. moim zdaniem – olleh

0

Mechanizm Upgrade IMO wymaga niestandardowej konfiguracji dla każdego modelu.

Najlepszym rozwiązaniem byłoby zaimplementowanie niestandardowego zapytania SQL dla modelu, np.

insert into <table> (<field_1>, ..., <field_n>) 
    values (<field_1_value>, ..., <field_n_value>) 
on duplicate key update 
    field_x = field_x_value, 
    ... 
    field_z = field_z_value; 
Powiązane problemy