2015-05-06 39 views
5

Bir model sayacını atomik olarak artırmalı ve yeni değerini (bir Sidekiq işi tarafından işlenmiş) kullanmalıyım. Şu anda Rails ve Postgres ile atomik sayacın değerini (artış) alın

, ben sayacı atomik artırır benim modelinde
Group.increment_counter :tasks_count, @task.id 

kullanın.

Ama Ayrıca sayaç varsa, bir bildirim göndermek için yeni değerine de ihtiyacım var. 50 değeri. Herhangi bir fikir? Tabloyu/satırı kilitlemek veya daha kolay bir yolu var mı?

Düzenleme/ÇÖZÜM mu dayanarak

'cevabı ve raylar en update_counters yöntem olup, I (PostgreSQL ile test edilmiştir) bir örnek yöntemi uygulamaya çok kısadır.

def self.increment_counter_and_return_value(counter_name, id) 
    quoted_column = connection.quote_column_name(counter_name) 
    quoted_table = connection.quote_table_name(table_name) 
    quoted_primary_key = connection.quote_column_name(primary_key) 
    quoted_primary_key_value = connection.quote(id) 

    sql = "UPDATE #{quoted_table} SET #{quoted_column} = COALESCE(#{quoted_column}, 0) + 1 WHERE #{quoted_table}.#{quoted_primary_key} = #{quoted_primary_key_value} RETURNING #{quoted_column}" 
    connection.select_value(sql).to_i 
end 

hoşuna kullanın:

Group.increment_counter_and_return_value(:tasks_count, @task.id) 

Aynı sorgu içinde yeni değeri getirmesi RETURNING kullanır.

cevap

5

Sizin Group.increment_counter çağrı veritabanına böyle SQL gönderir: X@task.id olduğunu

update groups 
set tasks_count = coalesce(tasks_counter, 0) + 1 
where id = X 

.

update groups 
set tasks_count = coalesce(tasks_counter, 0) + 1 
where id = X 
returning tasks_count 

olsa veritabanına o SQL almak için herhangi bir elverişli Railsy yol bilmiyorum: Yeni tasks_counter değeri elde etmek SQL yolu İADESİ maddesini eklemektir. Her zamanki Raylar yaklaşım olabilir ya kilitleme bir grup var ve @task yeniden veya kilitleme atlamak ve en iyisini umut ediyorum:

Group.increment_counter :tasks_count, @task.id 
@task.reload 
# and now look at @task.tasks_count to get the new value 

Sen gibi RETURNING kullanabilirsiniz olsa bu:

new_count = Group.connection.execute(%Q{ 
    update groups 
    set tasks_count = coalesce(tasks_counter, 0) + 1 
    where id = #{Group.connection.quote(@task.id)} 
    returning tasks_count 
}).first['tasks_count'].to_i 

Sen' d muhtemelen Group üzerindeki bir yöntemin arkasındaki bu karışıklığı gizlemek istersiniz böylece

+0

Bana bunu gösterdiğiniz için teşekkür ederiz. Sorumu, cevabınıza dayalı bir örnek yöntemiyle güncelledim. – tbuehl