Search code examples
ruby-on-rails-3paper-trail-gem

Rails 3, PaperTrail and Whodunnit User Instance


I have a City class which has versions controlled by PaperTrail. My system has users which are managed by Devise. I would like to have a relation between an User who edited a specific version of the City class.

To do so I have tried the following configuration using Rails 3.2.15 and Paper Trail 3.0.0:

class City < ActiveRecord::Base
  has_paper_trail
end

class User < ActiveRecord::Base
  has_many :editions, :foreign_key => 'whodunnit', :class_name => "PaperTrail::Version"
end

class PaperTrail::Version < ActiveRecord::Base
  belongs_to :user
end

With this I can have the editions made by a specific user, for example:

User.last.editions to get a list of editions (PaperTrail::Version objects) from the last user.

Then I thought it would be straightforward to have the instance of an user who edited a specific City, for example, to get the user instance of the user who edited the last version of the first City:

# NoMethodError: undefined method `user' for #<PaperTrail::Version:0x000000051d0da8>
City.first.versions.last.user

If it is not like this, how should I configure my models to have access to the "user" method on PaperTrail::Version?

Ps.: I am not sure that I should have created a Model PaperTrail::Version as I did, but I did not figured out another way in that direction.


Solution

  • Found the answer myself. Everything is based on subclassing the PaperTrail::Version and using the :class_name option. My working configuration is:

    class City < ActiveRecord::Base
      has_paper_trail, :class_name => 'Version'
    end
    
    class User < ActiveRecord::Base
      has_many :editions, :foreign_key => 'whodunnit', :class_name => "Version"
    end
    
    class Version < PaperTrail::Version
      belongs_to :user, :foreign_key => 'whodunnit'
    end
    

    And now when calling user for a specific version it returns the user whodunnit instance

    City.first.versions.last.user
    => #<User id: 2, email: "xxxxxx@yyyyy.com", encrypted_password: ...>