2011-02-02 3 views
5

Abbiamo un codice spesso colpiti nella nostra app che incrementa una colonna, in questo modo:Posso eseguire un incremento atomico in Rails 2.3 senza scendere a SQL?

if (r = customer.find_or_generate_reminder) 
    r.counter += 1 
    r.save! 
end 

stiamo ottenendo blocco timeout di attesa, così sto pensando di fare questo un'operazione atomica. Ingenuamente, quello che voglio fare è simile al seguente:

if (r = customer.find_or_generate_reminder) 
    connection.excute('UPDATE customer_reminders SET counter=counter+1, updated_at=now() WHERE id = ' + r.id) 
end 

Esiste un modo rubino mondo di fare la stessa cosa?

risposta

7

È possibile utilizzare il metodo della classe increment_counter:

Customer.increment_counter :counter, customer 

Che sarà creare qualcosa di simile:

UPDATE `customers` SET `counter` = COALESCE(`counter`, 0) + 1 WHERE (`customers`.`id` = 53) 

(si deve passare sia un id o di un'istanza della classe in questo metodo (customer) a differenza del metodo customer.increment!(:counter) che non è atomico)

1

Ho creato un gioiello per rendere questo più orientato agli oggetti:

https://github.com/imme5150/rails_atomic_increment

permette di fare:

customer.atomic_increment!(:counter) 

fatemi sapere cosa ne pensate.

+0

Ci siamo spostati su da questo problema, ma che sembra una buona soluzione. Grazie! – Simon

0

Se non ti dispiace un po 'di SQL:

CustomerReminder.where(id: id).update_all('counter = counter + 1, updated_at = now()')