Validation is ignored when cloning a newly created record

I have a model UserFilethat belongs_toa Folder:

class UserFile < ActiveRecord::Base
  has_attached_file :attachment
  belongs_to :folder

  validates_attachment_presence :attachment
  validates_presence_of :folder_id

  def copy(target_folder)
    new_file = self.clone
    new_file.folder = target_folder
    new_file.save!
  end
end

The following test terminates unexpectedly:

test 'cannot copy a file to anything other than a folder' do
  folder = Factory(:folder)
  file1 = UserFile.create(:attachment => File.open("#{Rails.root}/test/fixtures/textfile.txt"), :folder => Folder.root)
  file2 = UserFile.find(file1)

  # Should pass, but fails
  assert_raise(ActiveRecord::RecordInvalid) { file1.copy(nil) }

  # Same record, but this DOES pass
  assert_raise(ActiveRecord::RecordInvalid) { file2.copy(nil) }

  assert file1.copy(folder)
end

validates_presence_of :folder_idignored when using a newly created object, but when I do ActiveRecord#find, it works. I think this has something to do with the call clonein the method copy, but I can't figure it out. Does anyone know what is happening or how to pass the test?

+5
source share
1 answer

Mischa, cloning is a beast.

record.errors memoized, and the @errors instance variable is also cloned.

file1.errors = new_file.errors

, create file1.

, 1 new_file.save!? valid? errors.clear new_file, , 1. , :

def validate(record)
   record.errors.add_on_blank(attributes, options)
end

() errors.base http://apidock.com/rails/ActiveModel/Errors/add_on_blank

, new_file , ,

new_file.errors.instance_eval { @base } == file1

file1.folder_id .

, db, file2.errors nil, , , (), folder_id - new_file.folder = target_folder.

def copy(target_folder)
    new_file = self.clone
    new_file.instance_eval { @errors = nil } # forces new error object on clone
    new_file.folder = target_folder
    new_file.save!
end

,

+3

All Articles