2012-07-16 13 views
31

私はビュー数(整数)の変数を含むピクチャモデルを持っています。 誰かがピクチャオブジェクトを見るたびに、ビューカウントが+1されます。これを行うになって .increment vs + = 1

@picture.view_count += 1 
    @picture.save 

私は増分を使用している場合、.SAVE必要であるにも
@picture.increment(:view_count, by = 1) 

の違いは何ですか?

+1

は、構文は' @のpicture.incrementではないでしょうか? –

+0

並行性に注意してください!あなたの両方のソリューションはこの場合安全ではありません! 2人のユーザーが同時にコードを実行するとします。どちらも同じ 'view_count'値で動作します。次に、2番目のユーザーが保存時に最初のユーザーの値を上書きし、最終的なカウントが1未満になる。 これを避けるには、 'increment_counter'を使うべきです。 –

答えて

45

ソースは、以下のとおりです.nilの場合は属性をゼロに初期化し、by(デフォルトは1)として渡された値を追加します。保存しないので、まだ.saveが必要です。

def increment(attribute, by = 1) 
    self[attribute] ||= 0 
    self[attribute] += by 
    self 
end 
+24

または手動で保存したくない場合は 'increment!'メソッドを使うことができます –

+2

これはちょっと古いです、新しいメソッドはincrement_counterです – timroman

+0

このインクリメントの対象はリレーションでスコープできると思いますか? post has_many images、インクリメントする必要のある位置属性を持つイメージモデル – Ben

4

counter_cacheを使用してください。 counter_cacheは、レコード数を自動的に増やすのに役立ちます。

class Picture < ActiveRecord::Base 
    has_many :views 
end 

class View < ActiveRecord::Base 
    belongs_to :picture, counter_cache: true 
end 

写真のテーブルは、名前views_countでカラムを必要とするか、例えば、この列に独自の名前を使用することができます。

belongs_to :picture, counter_cache: :number_of_views 

しかし、私はあなたがviews_countあるcounter_cache列のデフォルト名を使用することをお勧めします。

+0

'モデルが必要なのでテーブルを必要としますか?それとも「抽象化」できますか? – Ben

20

この場合、よくcounter_cacheincrement_counterを使用します。このような

Picture.increment_counter(:view_count, @picture.id) 

この方法では、より簡単で、自作の方法よりも高速です。

なお、ActiveRecord :: CounterCacheにはdecrement_counterも含まれています。 (:VIEW_COUNT、1) `

http://api.rubyonrails.org/classes/ActiveRecord/CounterCache/ClassMethods.html

+2

これは最良の答えです。なぜなら、これは同時性を扱うからです。 –