class RevisionBuilder < Revision attr_reader :versionable, :version def initialize(args) @versionable = args[:versionable] @version = args[:version] build_revision end private def build_revision mark_for_removal build_attributes build_children end def mark_for_removal version.marked_for_removal = true if versionable.marked_for_destruction? end def build_attributes versionable_attributes.each do |attr| attr = AttributeEncapsulator.new(attr) if changed_attributes.include?(attr.key) build_attribute(attr) end end end def build_attribute(attr) version_attributes.build( name: attr.key, new_value: attr.value, old_value: previous_value(attr.key)) end def build_children nested_associations.each do |association| versionable.public_send(association).each do |child| build_child(child) end end end def build_child(child) if RevisionAuditor.new(child).changes_original? version_child = build_version_child(child) RevisionBuilder.new(versionable: child, version: version_child) end end def build_version_child(child) if child.new_record? version_children.build(versionable_type: child.class.name) else version_children.build(versionable: child) end end end