【问题标题】:.increment vs += 1.increment vs += 1
【发布时间】:2012-07-14 23:51:09
【问题描述】:

我有一个包含视图计数变量(整数)的图片模型。 每当有人查看 Picture 对象时,查看次数就会增加 +1。

在完成这件事上,有什么区别

   @picture.view_count += 1
   @picture.save

   @picture.increment(:view_count, 1)

如果我使用增量,是否需要 .save?

【问题讨论】:

  • 语法不应该是@picture.increment(:view_count, 1)吗?
  • 注意并发!在这种情况下,您的两种解决方案都不安全!想象一下两个用户同时运行代码。两者都使用相同的 view_count 值。然后第二个用户在保存时覆盖第一个用户的值,最终计数比预期的少一个。您应该使用increment_counter 来避免这种情况。

标签: ruby-on-rails ruby increment


【解决方案1】:

increment的来源如下,如果为nil,则将属性初始化为零,并加上传递的值(默认为1),它不做保存,所以.save仍然是必要的。

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

【讨论】:

  • 如果不想手动保存也可以使用increment!方法
  • 这有点过时了,新方法是increment_counter
  • 你认为这个增量的东西可以用关系来限定吗?发布 has_many 图像,图像模型具有需要递增的位置属性
  • @timroman 方法 increment_counter 适用于 Model 类,如果您有记录,您只需在其上调用 'increment' 以将值增加 1。
【解决方案2】:

您应该使用 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

但我建议您为 counter_cache 列使用默认名称,即 views_count。

【讨论】:

  • 那需要一个模型,因此需要一个表格?还是可以“抽象”?
【解决方案3】:

在这种情况下,我经常使用counter_cacheincrement_counter

像这样:

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

这种方法比自制方法更简单、更快捷。

顺便提一下,ActiveRecord::CounterCache 也有 decrement_counter

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

【讨论】:

  • 这是最好的答案,因为它负责并发。
猜你喜欢
  • 1970-01-01
  • 2013-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 2022-12-19
相关资源
最近更新 更多