我怎样才能做到这一点?
试图创建两个名为
的方法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)。
有什么建议吗?我不想创建另一个表来计算分页数。
答案 0 :(得分:90)
作为update_attribute
的替代方案,在Rails 3.1+中,您可以使用update_column
。
update_attribute
会跳过验证,但会触及updated_at
并执行回调。
update_column
跳过验证,不会触及updated_at
,也不会执行回调。
因此,如果您不想影响update_column
并且不需要回调,updated_at
是一个很好的选择。
有关详细信息,请参阅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
答案 1 :(得分:12)
Is there a way to avoid automatically updating Rails timestamp fields?
或者更接近你的问题:
http://blog.bigbinary.com/2009/01/21/override-automatic-timestamp-in-activerecord-rails.html
答案 2 :(得分:12)
如果您只想增加一个计数器,我会改用increment_counter
方法:
ModelName.increment_counter :pagehit, id
答案 3 :(得分:2)
为避免Monkeypatchingtroubles,你也可以使用ModelName.update_all:
def increment_pagehit
self.class.update_all({ pagehit: pagehit+1 }, { id: id })
end
这也不会触及记录上的时间戳。
答案 4 :(得分:2)
这样做不是一个好主意:
self.class.update_all({ pagehit: pagehit+1 }, { id: id })
应该是
self.class.update_all("pagehit = pagehit + 1", { id: id })
原因是如果两个请求是并行的,则在第一个版本上,两个请求都将使用相同的数字更新pagehits,因为它使用保存在Ruby内存中的数字。第二个选项使用sql server将数字增加1,如果其中两个查询同时出现,服务器将一个接一个地处理它们,并最终得到正确的分页数。
答案 5 :(得分:1)
答案 6 :(得分:0)
如果精确度不是那么重要,并且您不希望代码多次运行,您可以尝试更改数据库updated_at
中保存的值,如下所示:
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
替换它。