Rails 求助:如何记录可读的操作行为日志

will7v · 2016年05月18日 · 最后由 hfpp2012 回复于 2016年05月20日 · 3476 次阅读

求助大家个问题:

对于 Project(项目)这个 model,与之相关联的有很多其他 model,比如,文档 Documents( project has_many documents),意向 Interests(projects HABTM interests) 等

需求:

要记录下所有的操作行为日志,以后要获取查看,要记录的日志应该包括两部分 线索可读文本,可读文本是要后面输出的,所以想在保存日志的时候拼好存起来,到时直接输出可读文本,线索留底。

举个场景:

  1. 修改关联的对象,如 interests,线索类似是"interests: { amount: 20, rating: 5, ... }",输出的文本是"who 在 when 修改了 what(项目)的意向 aaa 的属性,新的值为 xxx"

  2. 做了某个动作,动作可以包括修改或创建多个对象,线索类似 { followers: 1, 2, 3, sector: 2, leader: 4 } , 输出的文本是"who 在 when 推进了项目,新的领导是 xxx4,新的协同者是 xxx1,xxx2,xxx3, 区域改为 中国"

想到的解决方案:

  1. 类似 event-sourcing 的方法,删除和修改(哪怕是一个字段的修改)只做增量,用 before_create 回调记录的日志 log,对应到某条记录:

参考:

Event Sourcing Taking D out of CRUD

遇到问题:

  • 碰到场景 2,本来想的效果是一条记录,现在会因为修改多个对象要记录多条
  • 某些对象有 is_removed 属性,就算记录了 version,前面的 version 是 is_removed: true,后面修改了的话,前面的还是会被查出来,除非删除的时候还要动原来的记录,这与全部增量的原则不符
  • 表可能会很大,如果要往另一个历史表迁就还要考虑其他问题,而且每个表都要对应出一个历史表
  1. 手动硬写,命令式记录日志,先用 changed_attributes 检查被修改的字段,针对每个要记录的动作手动 merge 其他线索,再 before_save 用动作对应的文本模版写文本

参考:

Dirty

  • 一点也不优雅,把代码搞的很难看,有时还会碰到问题(比如 grape declared(params),碰到这个效果
# controller
Project.transaction do
  project.remark = declared(params).remark
  project.logdown(503, @current_user, {})
  project.save
end
# model
def logdown(event_id, current_user, clue = {})
  clues = self.changed_attributes.merge(clue) # 这里拿到的self.changed_attributes 是{ "remark"=>"#<Hashie::Mash funding_id=1 remark=\"hello\">"} 
  logs.create!(user_id: current_user.id, event_id: event_id, clues_cached: cues)
end
  • 要针对每个动作写一个方法来拼线索和文本

求各位高手指点一个优雅点的方法,或者其他好的思路

paper_trail 等 gem 也考虑过,但是貌似其主要用途是为了记录版本回滚记录,并不是为了记录日志,没想到怎样定制保存可读文本,也遇到了方法一的问题,一个动作包括修改多个对象时,实际是产生了多条日志

我用的是 https://github.com/chaps-io/public_activity 对于多 model 的做法是在主 model 加一个 changes hash 变量 其他 model 的修改放到里面 在 controller 里 create activity 记录日志把 changes 变量存入

## model 涉及修改多 model 的方法
if old_weights != new_weights
  weights_changes = {weights: [old_weights, new_weights]}
  add_change weights_changes
end

## controller
if @promotion.save
  Activity.add_promotion @promotion, :create, current_user, changes: @promotion.attribute_changes
end

其实也没优雅多少..

需要 登录 后方可回复, 如果你还没有账号请 注册新账号