2011-01-14 22 views

risposta

13

Model.find_or_initialize probabilmente fa quello che vuoi. Puoi concatenarlo con save o update_attributes se questo ha senso.

Ulteriori informazioni nello Rails Guides.

+3

vedere il commento sulla risposta di Pasta – tybro0103

+1

Qualcuno ha visto questo generare un upsert? La guida dei binari indica che il nuovo oggetto non sarà ancora memorizzato nel DB, quindi non posso vedere come questo sia un vero upsert di DB. Ad esempio, non funzionerà in modo affidabile in un ambiente multi-thread. – stuckj

+2

Questa soluzione ha problemi di concorrenza. Fallirà se un altro thread aggiorna la tabella tra 'find_or_initialize' e' save'. –

3

C'è anche Model.find_or_create

+6

Questo non fa un upsert. Fa un select e poi (opzionalmente) un insert. Mentre ottieni lo stesso effetto in un mondo a thread singolo, in un mondo a più thread, ti servirà per eseguire un upsert effettivo. – tybro0103

-1

avevo scritto un post sul blog come possiamo ottenere questo. Dai un'occhiata a here.

Dovrai scrivere un'estensione di registrazione attiva. Assomiglierà a questo.

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

Non è un fan dell'uso degli errori per guidare il flusso logico previsto, specialmente quando è possibile prevedere quando si verificherà questo errore. – kmanzana

+0

buon punto @kmanzana. un po 'troppo hackerato per me. A parer mio – olleh

0

Il meccanismo IMO Upsert richiede una configurazione personalizzata per ciascun modello.

Quindi la soluzione migliore sarebbe implementare una query SQL personalizzata per un modello, ad es.

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;