0

我有一个 Rails 站点,它记录了一些简单的操作,例如人们对信息的支持和反对。对于每一个新动作,EventLog都会创建一个。

如果用户改变主意怎么办?我有一个after_create回调,它寻找补充动作并在找到最近的一对时删除两者。为清楚起见,我的意思是,如果一个人对某事表示赞成并很快取消,则两者event_logs都将被删除。接下来是我的回调。

# Find duplicate events by searching nearly all the fields in the EventLog table
@duplicates = EventLog.where("user_id = ? AND event = ? AND project_id = ? AND ..., ).order("created_at DESC")

if @duplicates.size > 1
  @duplicates.limit(2).destroy_all
end

上面的代码不太有效,因为如果任何字段恰好为 nil,则查询返回[].

我如何编写此代码以便它可以处理空值,和/或有更好的方法来完全做到这一点?

4

2 回答 2

0

如果我理解正确的话,

某些字段可以为 nil,而您想要查找具有相同 user_id、相同 project_id 或项目 id 的活动日志可以为 nil。

所以我想这个查询应该适合你。

ActivityLog.where(user_id: <some_id> AND activity: <complementary_id> AND :project_id.in => [<some_project_id>, nil] ....)

这样,您将获得 user_id 相同且项目 ID 可能存在或不存在的补充事件日志

class ActivityLog
  QUERY_HASH = Proc.new{ {user_id: self.user_id, 
                         activity: complementary_id(self.id),
                         and so on....
  } }
于 2013-07-10T09:41:34.257 回答
0

怎么样:

# event_log.rb

def duplicate_attr_map
  {
    :user_id,
    :project_id
  }
end

def duplicates
  attribs = duplicate_attr_map.reject_if(&:blank?)

  query  = attribs.map { |attr| "#{attr} = ?" }.join(' AND ')
  values = attribs.map { |attr| self.send(attr) }

  EventLog.where(query, *values).order("created_at DESC")
end

def delete_duplicates(n)
  duplicates.limit(n).delete_all if duplicates.size > 1
end

# usage:
# EventLog.find(1).delete_duplicates(2)

未测试,有待改进

于 2013-07-11T09:08:46.583 回答