ruby on rails-如何在没有触摸updated_at属性的情况下更新单个属性?

我该如何实现?

试图创建2个方法,称为

def disable_timestamps
  ActiveRecord::Base.record_timestamps = false
end

def enable_timestamps
  ActiveRecord::Base.record_timestamps = true
end

和更新方法本身:

def increment_pagehit
  update_attribute(:pagehit, pagehit+1)
end

使用以下回调打开和关闭时间戳:

before_update :disable_timestamps, :only => :increment_pagehit
after_update :enable_timestamps, :only => :increment_pagehit

但它没有更新任何内容,甚至没有更新所需的属性(pagehit)。

有什么建议吗? 我不想创建另一个表只是为了统计页面点击数。

Kleber S. asked 2020-07-11T22:14:29Z
7个解决方案
93 votes

作为update_column的替代产品,在Rails 3.1+中,您可以使用updated_at

update_column跳过验证,但会触摸updated_at并执行回调。

update_column跳过验证,不接触updated_at,并且不执行回调。

因此,如果您不想影响updated_at并且不需要回调,则update_column是一个不错的选择。

有关更多信息,请参见[http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html]。

另请注意,update_column将更新内存模型中的属性值,并且不会将其标记为脏。 例如:

p = Person.new(:name => "Nathan")
p.save
p.update_column(:name, "Andrew")
p.name == "Andrew" # True
p.name_changed? # False
Nathan answered 2020-07-11T22:15:40Z
12 votes

如果您要做的只是增加一个计数器,我将使用increment_counter方法代替:

ModelName.increment_counter :pagehit, id
idlefingers answered 2020-07-11T22:16:00Z
11 votes

有没有办法避免自动更新Rails时间戳字段?

或更接近您的问题:

[HTTP://blog.big binary.com/2009/01/21/override-automatic-timestamp-in-active record-rails.HTML]

apneadiving answered 2020-07-11T22:14:58Z
2 votes

为了避免Monkeypatching麻烦,您还可以为此使用ModelName.update_all:

def increment_pagehit
  self.class.update_all({ pagehit: pagehit+1 }, { id: id })
end

这也不会影响记录上的时间戳。

fredostarr answered 2020-07-11T22:16:24Z
2 votes

这样做不是一个好主意:

self.class.update_all({ pagehit: pagehit+1 }, { id: id })

它应该是

self.class.update_all("pagehit = pagehit + 1", { id: id })

原因是如果两个请求是并行的,则在第一个版本中,两个请求都将使用相同的数字来更新Pagehit,因为它使用的是Ruby内存中保存的数字。 第二个选项使用sql服务器将数字增加1,以防万一其中两个查询同时出现,服务器将一个接一个地处理它们,并以正确的pagehit数结束。

Tom Caspy answered 2020-07-11T22:16:53Z
1 votes

您也有updated_atupdated_at(以及它们的bang版本),它们不会更改updated_at,不会触发验证回调,并且对于计数器/整数显然很方便。

tirdadc answered 2020-07-11T22:17:13Z
0 votes

如果精度不是那么重要,并且您不希望代码运行多次,则可以尝试更改数据库Time.now中保存的值,如下所示:

u = User.first
u.name = "Alex 2" # make some changes...
u.updated_at = u.updated_at + 0.000001.second # alter updated_at
u.save

因此,Rails实际上将尝试保存相同的值,而不是将其替换为Time.now

glampr answered 2020-07-11T22:17:38Z
translate from https://stackoverflow.com:/questions/4887668/how-to-update-a-single-attribute-without-touch-updated-at-attribute