PaperTrail: info_for_paper_trail outside the context of a controller
Asked Answered
M

2

5

I am using the paper_trail gem for versioning my models.

So far, my model depends on the info_for_paper_trail method in ApplicationController:

class ApplicationController < ActionController::Base
  # Extra columns to store along with PaperTrail `versions`
  def info_for_paper_trail
    { revision_id: @revision.id, revision_source_id: @revision_source.id }
  end
end

This works great in context of the controller, but is there a way that I can replicate this sort of thing outside the context of the controller (e.g., a delayed job)?

I tried creating a virtual attribute called revision and passing a proc into has_paper_trail, but it errors out with a method not found exception:

# Attempt to solve this in the model
class Resource < ActiveRecord::Base
  # Virtual attribute
  attr_accessor :revision

  # Attempt to use virtual attribute only if set from delayed job
  has_paper_trail meta: proc { |resource| resource.revision.present? ? { revision_id: resource.revision.id, revision_source_id: revision.revision_source.id } : {} }
end

# Gist of what I'm trying to do in the delayed job
resource = Resource.new
resource.revision = Revision.new(user: user, revision_source: revision_source)
resource.save!

I assume based on this result that meta cannot take a proc, and plus I don't like how this solution smells anyway...

Mesomorph answered 31/7, 2013 at 12:31 Comment(0)
M
8

You need to set these values in your code if you're operating outside of the controller:

::PaperTrail.controller_info = { revision_id: revision.id, revision_source_id: revision_source.id }
::PaperTrail.whodunnit = user.id

The model will then pick the extra values up just like it would normally from the controller.

I derived this info from looking at the PaperTrail::Controller module. Particularly, look at the set_paper_trail_controller_info and set_paper_trail_whodunnit methods that get run as before filters.

Mesomorph answered 1/8, 2013 at 13:43 Comment(0)
K
1

I think you can just do:

class Resource < ActiveRecord::Base
  # Virtual attribute
  attr_accessor :revision, :revision_source

  # Attempt to use virtual attribute only if set from delayed job
  has_paper_trail meta: { 
    revision_id: :get_revision_id, 
    revision_source_id: get_revision_source.id 
  }

  def get_revision_id
    resource.revision.try(:id)
  end

  def get_revision_source_id
    resource.revision_source.try(:id)
  end
end
Kindliness answered 1/6, 2016 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.