@@ -33,5 +33,87 @@ module VersionConcern
3333 #def reify(options = {})
3434 # super
3535 #end
36+
37+ module ClassMethods
38+ def changeset ( options = { } )
39+ super ( )
40+ return @changeset unless ::PaperTrail . config . track_associations?
41+
42+ @changeset = load_changeset_has_many_through ( @changeset ) if options [ :has_many_through ]
43+ @changeset
44+ end
45+
46+ private
47+
48+ def load_changeset_has_many_through ( changes )
49+ has_many_through_assocs
50+ . reduce ( changes ) do |acc , assoc |
51+ assoc_changes = has_many_through_changes ( assoc )
52+ acc . merge! ( assoc_changes ) if assoc_changes . any?
53+
54+ acc
55+ end
56+
57+ changes
58+ end
59+
60+ def has_many_assocs
61+ item_type . to_s . classify . constantize
62+ . reflect_on_all_associations ( :has_many )
63+ end
64+
65+ def has_many_through_assocs
66+ has_many_assocs
67+ . select { |assoc | assoc . through_reflection? }
68+ end
69+
70+ def paper_trail_enabled? ( assoc )
71+ ::PaperTrail . request . enabled_for_model? ( assoc . klass ) ||
72+ ( assoc . through_reflection? && ::PaperTrail . request . enabled_for_model? ( assoc . through_reflection . klass ) )
73+ end
74+
75+ def has_many_through_changes ( assoc )
76+ return { } unless object_changes . present?
77+
78+ versions = find_associated_versions ( assoc . through_reflection )
79+
80+ return { "#{ assoc . name } " : updated_changes ( assoc , versions ) } if updated_changes ( assoc , versions ) . any?
81+
82+ { "#{ assoc . name } " : [ removed_changes ( assoc , versions ) , added_changes ( assoc , versions ) ] }
83+ end
84+
85+ def find_associated_versions ( assoc )
86+ ::PaperTrail ::Version . where ( item_type : assoc . class_name , transaction_id : transaction_id )
87+ . joins ( :version_associations )
88+ . where ( version_associations : { foreign_key_name : assoc . foreign_key , foreign_key_id : item_id } )
89+ . order ( 'versions.created_at desc' )
90+ end
91+
92+ def updated_changes ( assoc , versions )
93+ versions . select { |version | version . event == "update" }
94+ . map ( &:changeset )
95+ . pluck ( assoc . foreign_key )
96+ . flat_map do |change |
97+ [
98+ assoc . klass . find_by ( id : change . first ) ,
99+ assoc . klass . find_by ( id : change . second )
100+ ]
101+ end
102+ end
103+
104+ def added_changes ( assoc , versions )
105+ versions . select { |version | version . event == "create" }
106+ . map ( &:changeset )
107+ . pluck ( assoc . foreign_key )
108+ . map { |change | assoc . klass . find_by ( id : change . second ) }
109+ end
110+
111+ def removed_changes ( assoc , versions )
112+ versions . select { |version | version . event == "destroy" }
113+ . map ( &:changeset )
114+ . pluck ( assoc . foreign_key )
115+ . map { |change | assoc . klass . find_by ( id : change . first ) }
116+ end
117+ end
36118 end
37119end
0 commit comments