paper_trail: Reify on associations fails if using Single Table Inheritance

It appears as though if Single Table Inheritance is being used on an association, if you try to reify with has_many: true or has_one: true, it will not find and build the previous version of the association and instead always use the current version of the association when browsing previous versions.

I believe this is happening because if STI is used, the item_type is always stored as the base class. But when calling the method reify_has_many_directly, it is using the main class of the association. This builds a WHERE clause that is looking for the wrong value in the item_type column.

ex:

class Document < ActiveRecord::Base
  has_paper_trail
  has_one :authorship
end

class Assignment < ActiveRecord::Base
  belongs_to :document 
end

class Authorship < Assignment
  has_paper_trail
end

@document.reify(has_many: true, has_one: true)

The last line there will produce a SQL query like this:

SELECT  `versions`.* FROM `versions` 
INNER JOIN `version_associations` ON `version_associations`.`version_id` = `versions`.`id` 
WHERE (version_associations.foreign_key_name = 'document_id') 
AND (version_associations.foreign_key_id = 1) 
AND (versions.item_type = 'Authorship') 
AND (created_at >= '2015-08-26 20:07:28.000000' OR transaction_id = 933)  
ORDER BY versions.id ASC LIMIT 1

But item_type will never be ‘Authorship’, it is always stored as Assignment. I’m still working on figuring out a solution to this if I can, but this seems to be what is happening from my understanding.

Modifying the database manually and changing the item_type column from Assignment to Authorship results in being able to view the correct versions of the association as I browse through the document history.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 23 (18 by maintainers)

Commits related to this issue

Most upvoted comments

I worked with Kevin on this, your gist does reproduce the issue. Here’s another one too:

https://gist.github.com/daneshd/f0e61744075e1617dbcb

I was working on a fix for this issue but I haven’t had the time to finish it. One thing I noticed in your report is you’d like the item_type to be Authorship. I went down that path when patching paper_trail but it didn’t work out. I eventually found this

Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association.

Saving item_type to the child model instead of the base model caused issues with how it was loaded.

I tried to change the way the lookup was done to grab all the versions whose class is the base model here. I only started on the reify_has_ones.

- where("#{version_table_name}.item_type = ?", assoc.class_name).
+ where("#{version_table_name}.item_type = ?", assoc.klass.base_class.name).

This isn’t enough though. You could have more than 1 record saved with the base class if your model uses other has_one associations of the same STI base model (e.g. the sponsorship model in my bug report). Say I have a user that has an authorship and a sponsorship, then there would be 2 version records whose base class is Assignment and whose foreign key is my user’s id.

I tried iterating through the found versions to lookup and filter these by their type. I wasn’t sure about this approach because I had to force PT to never skip/ignore the type attributes, and it meant serializing the object data to figure out which to use.

Our implementation for versioning things caused some other issues for me so I had to put this fix on hold to figure that out. I never got around to reify_has_manys.

Thanks to André’s work in https://github.com/airblade/paper_trail/pull/1028 this issue is partially fixed and released as 8.1.2. Also thanks to André, we have a failing (skipped) test in person_spec.rb that should demonstrate the remaining issue.

I was working on a fix for this issue …

Danesh, have you done any more work on this since January? Is it still an issue with the latest version (currently 5.1.1)? Thanks.

I think it may be better to say that it’s a known issue instead.

https://github.com/airblade/paper_trail#5a-single-table-inheritance-sti now mentions this issue (#594) as a known issue.