呼ばれるたびに前回返した値から+1したものを返すカウンターのクラスを書いたものの、出番がなくなったが、今後同じようなものを書きそうなのでメモ。 動作はMySQLで試した。
テーブルの定義
class CreateCounters < ActiveRecord::Migration def change create_table :counters do |t| t.string :key t.integer :count, :default => 0 t.timestamps end add_index :counters, :key end end
クラス定義
class Counter < ActiveRecord::Base class << self def next(key) find_or_create_by_key(key).next end end validates_presence_of :key, :count validates_uniqueness_of :key def next with_lock do increment! :count count end end end
使い方
# クラスメソッドで使う Counter.next('foo') # => 1 Counter.next('foo') # => 2 Counter.next('foo') # => 3 # 違うキーを使うと別のカウンター扱いになる Counter.next('bar') # => 1 # インスタンス化して使う counter = Counter.find_or_create_by_key 'foo' counter.next # => 4 # 同じキーで別のインスタンスを作ると互いに影響する counter2 = Counter.find_or_create_by_key 'foo' counter2.next # => 5 counter.next # => 6 counter2.next # => 7