4

有一个典型的博客应用程序。每个用户都有_many 个帖子。每个帖子都有_many标签。我按 updated_at 对每个帖子进行排序,因此最近更新的帖子将显示在顶部。因此,例如,如果我更新帖子的内容,该帖子将出现在顶部。但是,当我只添加一个标签时也会发生这种情况,因为一个标签连接到其相应的帖子。

我只希望内容更新更改 updated_at 字段。我不希望 updated_at 更改帖子,因为我添加了标签。有没有办法做到这一点?或任何其他方式来实现这样的事情?谢谢!

4

2 回答 2

4

我想到了两种方法:

  1. 不要:updated_at用于您使用它的目的。而是创建一个新列,例如:post_updated_at,并在每次保存时手动更新它,以使帖子移动到顶部。Rails 为此提供了一种方便的模型方法:

    mypost.touch :post_updated_at
    
  2. 当您更新列并希望:updated_at保持不变时,请使用该#update_column方法,该方法直接使用您给它的值更新数据库中的列。请注意,它将值逐字写入数据库,因此如果有问题的列是花哨的serialize列或类似的列,您必须很聪明。

于 2012-04-06T04:41:00.633 回答
0

这是一个替代品,save可让您将“无聊”属性列入黑名单,即那些不触发时间戳更新的属性。它依赖 Rails 4+update_columns方法在保存期间抑制回调方法(小心抑制这些方法)。

# Here we configure attribs that won't trigger the timestamp update
IGNORED_ATTRIBS = Set.new %w(reviewed_at view_count)

# A "save" replacement
def fussy_save

  # Calculate any ignored attributes that are pending a save
  all_changed_attribs = Set.new(self.changed_attributes.keys)
  ignored_changed_attribs = IGNORED_ATTRIBS.intersection all_changed_attribs

  # Save the ignored attributes without triggering updated_at
  if ignored_changed_attribs.present?
    self.update_columns self.attributes.slice(*ignored_changed_attribs)
  end

 # perform a normal save only if there are additional attributes present
  if !all_changed_attribs.subset?(IGNORED_ATTRIBS)
    save
  end

end

实施说明:

上面的最后一行是常规保存。我最初尝试在没有检查的情况下进行保存,基于如果已保存忽略的属性则不会发生任何事情(因为save什么都不做,并且如果没有保存属性,则不会更新时间戳)。但我发现这changed_attributes实际上是 Rails 内部的、明确的、参考,而不仅仅是对开发人员的方便(不太令人惊讶:)。开始弄乱它感觉很危险,所以我只是执行检查,所有更改的属性都将保存在 SQL 中(包括刚刚由 update_columns 保存的属性),但前提是存在未忽略的属性。

于 2015-05-07T18:25:28.240 回答