Repository: rails/rails
File: activerecord/lib/active_record/associations/collection_proxy.rb (Ruby)

Code before:
      def reset_scope # :nodoc:
        @offsets = @take = nil
        @scope = nil
        self
      end

      def inspect # :nodoc:
        load_target if find_from_target?
        super
      end

      def pretty_print(pp) # :nodoc:
        load_target if find_from_target?
        super
      end

      %w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
        class_eval <<~RUBY, __FILE__, __LINE__ + 1
          def #{method}(...)
            if loaded? && @association&.target&.any? { |r| r.new_record? }
              ActiveRecord.deprecator.warn(<<~MSG)
                Using #{method} on association with unpersisted records
                (\#{to_a.reject(&:persisted?).map(&:class).uniq.join(', ')})
                is deprecated. The unpersisted records will be lost after this operation.
                Please either persist your records first or store them separately before
                calling #{method}. This will become an error in Rails 8.1.
              MSG
              scope.#{method}(...)
            else
              scope.#{method}(...).tap { reset }
            end
          end
        RUBY
      end

      delegate_methods = [
        QueryMethods,
        SpawnMethods,
      ].flat_map { |klass|
        klass.public_instance_methods(false)
      } - self.public_instance_methods(false) - [ :select ] + [ :scoping, :values, :load_async ]

      delegate(*delegate_methods, to: :scope)

      private
        def find_nth_with_limit(index, limit)
          load_target if find_from_target?
          super
        end

        def find_nth_from_last(index)

Review comment (bug):
I don't think we will ever error. We don't when `update_all` is called with unpersisted records

Code after:
      def reset_scope # :nodoc:
        @offsets = @take = nil
        @scope = nil
        self
      end

      def inspect # :nodoc:
        load_target if find_from_target?
        super
      end

      def pretty_print(pp) # :nodoc:
        load_target if find_from_target?
        super
      end

      %w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
        class_eval <<~RUBY, __FILE__, __LINE__ + 1
          def #{method}(...)
            if @association&.target&.any? { |r| r.new_record? }
              association_name = @association.reflection.name
              ActiveRecord.deprecator.warn(<<~MSG)
                Using #{method} on association \#{association_name} with unpersisted records
                is deprecated. The unpersisted records will be lost after this operation.
                Please either persist your records first or store them separately before
                calling #{method}.
              MSG
              scope.#{method}(...)
            else
              scope.#{method}(...).tap { reset }
            end
          end
        RUBY
      end

      delegate_methods = [
        QueryMethods,
        SpawnMethods,
      ].flat_map { |klass|
        klass.public_instance_methods(false)
      } - self.public_instance_methods(false) - [ :select ] + [ :scoping, :values, :load_async ]

      delegate(*delegate_methods, to: :scope)

      private
        def find_nth_with_limit(index, limit)
          load_target if find_from_target?
          super
        end

        def find_nth_from_last(index)