0

我使用 rails 5 / audited 4.6.5 我一次对 2000 多个项目执行批处理操作。为了使它可用,我需要使用 updatre_all 函数。

然后,我想一次性创建所需的审核

我想做的是这样的:

Followup.where(id: ids).in_batches(of: 500) do |group|
  #quick update for user responsiveness
  group.update_all(step_id: 1)
  group.delay.newAudits(step_id: 1)
end

但是经过审核的宝石看起来是基本的。我敢肯定很多人以前都面临过这样的问题

4

2 回答 2

1

经过大量迭代,我设法创建了一个优化的查询。我把它放在一个 AditBatch 类中,还添加了延迟

class AuditBatch


############################################
## Init a batch update from a list of ids
## the aim is to avoid instantiations in controllers
## @param string class name (eq: 'Followup')
## @param int[] ids of object to update
## @param changet hash of changes {key1: newval, key2: newval}
############################################

def self.init_batch_creation(auditable_type, auditable_ids, changes)
    obj = Object.const_get(auditable_type)
    group = obj.where(id: auditable_ids)
    AuditBatch.delay.batch_creation(group, changes, false)
end

############################################
## insert a long list of audits in one time
## @param group array array of auditable objects
## @param changet hash of changes {key1: newval, key2: newval}
############################################
 def self.batch_creation(group, changes, delayed = true)

  sql = 'INSERT INTO audits ("action", "audited_changes", "auditable_id", "auditable_type", "created_at", "version", "request_uuid") 
  VALUES '

  total = group.size
  group.each_with_index  do |g, index|

    parameters = 'json_build_object('
    length = changes.size
    i=1
    changes.each do |key, val|
      parameters += "'#{key}',"
      parameters += "json_build_array("
      parameters += "(SELECT ((audited_changes -> '#{key}')::json->>1) FROM audits WHERE auditable_id = #{g.id} order by id desc limit 1),"
      parameters += val.is_a?(String) ? "'#{val.to_s}'" : val.to_s 
      parameters += ')'
      parameters += ',' if i < length
      i +=1
    end
    parameters += ')'

    sql += "('update', #{parameters}, #{g.id}, '#{g.class.name}', '#{Time.now}', (SELECT max(version) FROM audits where auditable_id= #{g.id})+1, '#{SecureRandom.uuid}')"
    sql += ", " if (index+1) < total
  end
  if delayed==true
    AuditBatch.delay.execute_delayed_sql(sql)
  else
    ActiveRecord::Base.connection.execute(sql)
 end

 end

def self.execute_delayed_sql(sql)
  ActiveRecord::Base.connection.execute(sql)
end
end
于 2017-11-09T12:53:11.860 回答
0

随着group.update_all您的回调被跳过,它最终不会在新审计中记录更改。

您无法为这些记录手动创建审核,即使您可以手动创建审核更改,您也需要参考“更改了什么?” (进去audited_changes)。update_all但是当您之前进行时,这些更改已经丢失group

(`action`, `audited_changes`, `auditable_id`, `auditable_type`, `created_at`, `version`, `request_uuid`)

它也记录在这个经过审计的问题中 - https://github.com/collectiveidea/audited/issues/352

paper_trail是另一个保留 change_logs 的 gem,也有这个问题: https ://github.com/airblade/paper_trail/issues/337

于 2017-10-26T09:01:07.880 回答