PaperTrail Manually create version

让人想犯罪 __ 提交于 2020-07-08 06:57:10

问题


I have a spreadsheet of items which I convert to CSV and import using a custom import script into my Rails based application.

The spreadsheet contains a row for each record but some rows hold different versions of previous rows.

When importing the CSV I currently mark the second row using a "past_version" field but I am now thinking that implementing a full versioning gem would be a much nicer way of going about it.

I have been reading through the docs for PaperTrail and it looks perfect for what I am after, however, I need the versions of some rows to be created as part of my import script. Can this be done with PaperTrail?

Basically I need to start an import, say record 1, 2, 3, 4, 5 are added normally, then record 6 is actually a newer version of record 2 and so I now need to manually create a PaperTrail version.

Is this possible?


回答1:


@Flori's touch_with_version approach worked, but paper_trail deprecated this method when they made touch a recordable event.

On the latest version of paper_trail, you can just do:

model.paper_trail.save_with_version

If you are on an older version, and this is not available, you can use the record_update method (this is what save_with_version uses internally):

model.paper_trail.record_update(force: true, in_after_callback: false)

There is no way to customize the event... you can do create, restore, update and touch but can't do something like record it as 'manual' at least not without a lot of monkey patching or something.

Even doing this is a little treacherous, since you're calling some internals that could change in future versions. It has some required params, also, that have changed from version to version.

In my case, I am using paper_trail and paranoia together and wanted to record an explicit version on restore which seems to bypass paper_trail unless you do something like the above.




回答2:


In case anyone stumble upon this issue: It's possible! You can call touch_with_version on any PaperTrail model like this: mymodel.paper_trail.touch_with_version. It will create a version for you.




回答3:


For PaperTrail 4.0.0 and Rails 4.2.0

I had to manually create my own version so that I could use the update_column method (which would otherwise not trigger PaperTrail.

#instance method in model to generate new version and create object_changes

  def generate_version!(object_attrs, changed_attrs)
     object_changes_attrs = {}
     changed_attrs.each do |k, v|
       object_changes_attrs[k] = v
     end
     object_value = self.class.paper_trail_version_class.object_col_is_json? ? object_attrs : PaperTrail.serializer.dump(object_attrs)
     object_changes_value = self.class.paper_trail_version_class.object_col_is_json? ? object_changes_attrs : PaperTrail.serializer.dump(object_changes_attrs)
     data = {
       event: 'update', # or any custom name you want
       whodunnit: PaperTrail.whodunnit,
       object: object_value,
       object_changes: object_changes_value
     }
     send(self.class.versions_association_name).create! merge_metadata(data)
   end

Then in your model you can call it wherever you want passing in: (1) a hash of the current object attributes (before the update); and (2) a hash of the attributes and changes made

#some method where you do not otherwise trigger PaperTrail

def my_method
  old_updated_at = self.updated_at
  new_updated_at = DateTime.now.utc
  object_attrs = self.attributes
  self.update_columns(prioritized: true, updated_at: new_updated_at)
  self.generate_version!(object_attrs, { 'prioritized': [false, true], 'updated_at': [old_updated_at, new_updated_at] })
end


来源:https://stackoverflow.com/questions/27804421/papertrail-manually-create-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!