How to initialize PaperTrail versions to perform bulk insert using ActiveRecord-import gem?
Asked Answered
G

1

6

I'm using activerecord-import gem to import multiple ActiveRecord documents in single query. Then I'm initializing related associations using saved documents ids and importing them too, and so on.

However, I need to have PaperTrail gem versions with create event for all saved documents.

Is there some straightforward way to initialize them to make possible perform bulk insert then?

NOTE: AR-Import gem ignores all callbacks, so I have manually handle them after importing.

Thanks!


UPD-20/05/17:

At the moment I've solved this with the patch for PaperTrail::Model. Here is my .../initializers/paper_trail.rb:

module PaperTrail
  class Version < ActiveRecord::Base
    ...    
  end

  module ModelPatch
    extend ActiveSupport::Concern

    included do
      # new method added to PaperTrail::Model module to make possible initialize
      # `create` versions right after importing resources.
      # This method contains modified code from private PaperTrail::Model::InstanceMethods#record_create
      # Difference:
      #  - instead of `create!` we use `new` but with validation and raise exception if it's invalid.
      # This is for reinsurance that if something changes after update PaperTrail gem in future
      # everything still works or need to fix it.
      def initialize_record_create_version
        return nil unless paper_trail_switched_on?
        data = {
          event:     paper_trail_event || 'create',
          whodunnit: PaperTrail.whodunnit
        }

        if changed_notably? && self.class.paper_trail_version_class.column_names.include?('object_changes')
          data[:object_changes] = if self.class.paper_trail_version_class.object_changes_col_is_json?
            changes_for_paper_trail
          else
            PaperTrail.serializer.dump(changes_for_paper_trail)
          end
        end
        new_v = send(self.class.versions_association_name).new merge_metadata(data)
        new_v.valid? ? new_v : fail("Invalid PaperTrail Version: #{new_v.errors&.messages}")
      end
    end
  end
end

PaperTrail::Model.send(:include, PaperTrail::ModelPatch)

UPD-28/01/21:

with PaperTrail v10.x.x works this:

  def initialize_record_create_version
    return nil unless paper_trail.enabled?

    event = Events::Create.new(self, false)
    data = event.data.merge!(paper_trail.data_for_create)
    new_v = send(self.class.versions_association_name).new data
    new_v.valid? ? new_v : fail("Invalid PaperTrail Version: #{new_v.errors&.messages}")
  end
Goddord answered 16/3, 2017 at 22:35 Comment(3)
I tried using this patch but its not working, can you please help?Gaitan
@MohdAnas that worked with older PaperTrail version. Updated solution for version 10.x.x. Haven't tested with the latest 11.x.x yet.Goddord
@BorysPylhun any update? Couldn't get this to work.Metaplasm
B
0

Yes, it should be possible to bulk-insert records into your versions table.

insert into versions
(item_id, item_type, event, created_at)
(1, "User", "create", "2016-02-29"),
(2, "User", "create", "2016-02-29"),
(1, "Widget", "create", "2016-02-29")

Because it is possible with plain SQL, it is also possible with ActiveRecord. Remember, PaperTrail::Version is a regular AR model.

Blanco answered 10/5, 2017 at 20:44 Comment(2)
I knew this. I need to find out different thing - how to initialize versions for just initialized AR-objects from inside the paper trail. This is a problem because they use only :after_create callback which is ignored and useless when I'm initializing and performing bulk insert. I found a temprorary solution for this using patch though.Goddord
I've just updated my question and included my current solution with the patch.Goddord

© 2022 - 2024 — McMap. All rights reserved.