# File lib/paper_trail/reifier.rb, line 10
      def reify(version, options)
        options = options.dup

        options.reverse_merge!(
          :version_at => version.created_at,
          :mark_for_destruction => false,
          :has_one    => false,
          :has_many   => false,
          :unversioned_attributes => :nil
        )

        attrs = version.class.object_col_is_json? ?
          version.object :
          PaperTrail.serializer.load(version.object)

        # Normally a polymorphic belongs_to relationship allows us to get the
        # object we belong to by calling, in this case, `item`.  However this
        # returns nil if `item` has been destroyed, and we need to be able to
        # retrieve destroyed objects.
        #
        # In this situation we constantize the `item_type` to get hold of the
        # class...except when the stored object's attributes include a `type`
        # key.  If this is the case, the object we belong to is using single
        # table inheritance and the `item_type` will be the base class, not the
        # actual subclass. If `type` is present but empty, the class is the base
        # class.

        if options[:dup] != true && version.item
          model = version.item
          # Look for attributes that exist in the model and not in this
          # version. These attributes should be set to nil.
          if options[:unversioned_attributes] == :nil
            (model.attribute_names - attrs.keys).each { |k| attrs[k] = nil }
          end
        else
          inheritance_column_name = version.item_type.constantize.inheritance_column
          class_name = attrs[inheritance_column_name].blank? ?
            version.item_type :
            attrs[inheritance_column_name]
          klass = class_name.constantize
          # The `dup` option always returns a new object, otherwise we should
          # attempt to look for the item outside of default scope(s).
          if options[:dup] || (_item = klass.unscoped.find_by_id(version.item_id)).nil?
            model = klass.new
          elsif options[:unversioned_attributes] == :nil
            model = _item
            # Look for attributes that exist in the model and not in this
            # version. These attributes should be set to nil.
            (model.attribute_names - attrs.keys).each { |k| attrs[k] = nil }
          end
        end

        model.class.unserialize_attributes_for_paper_trail! attrs

        # Set all the attributes in this version on the model.
        attrs.each do |k, v|
          if model.has_attribute?(k)
            model[k.to_sym] = v
          elsif model.respond_to?("#{k}=")
            model.send("#{k}=", v)
          else
            version.logger.warn(
              "Attribute #{k} does not exist on #{version.item_type} (Version id: #{version.id})."
            )
          end
        end

        model.send "#{model.class.version_association_name}=", version

        unless options[:has_one] == false
          reify_has_ones version.transaction_id, model, options
        end

        unless options[:has_many] == false
          reify_has_manys version.transaction_id, model, options
        end

        model
      end