activerecord-import icon indicating copy to clipboard operation
activerecord-import copied to clipboard

Model#valid? Returning True For Invalid Records After Import

Open Numie opened this issue 1 year ago • 7 comments

When I attempt to import a record that is invalid due to a uniqueness constraint, a number of ActiveModel methods are returning unexpected results. Specifically, valid? returns true after the import despite the record being invalid.

For example, I have a Post model with name and company_id attributes and a uniqueness validation like validates :name, uniqueness: { scope: :company_id }.

post = Post.first.dup
=>
#<Post:0x00007f6780ea8348
 id: nil,
 name: "Name",
 company_id: 1,
 created_at: nil,
 updated_at: nil>

post.valid?
=> false

post.new_record?
=> true

Then if I run an import, the return values change:

options = { validate: true, validate_uniqueness: true, recursive: true, all_or_none: true, track_validation_failures: true }
Post.import([post], options)
=> 
#<struct ActiveRecord::Import::Result
 failed_instances=
  [[0,
    #<Post:0x00007f6780ea8348
     id: nil,
     name: "Name",
     company_id: 1,
     created_at: nil,
     updated_at: nil>]],
 num_inserts=0,
 ids=[],
 results=[]>

post.valid?
=> true

post.new_record?
=> false

Post.new(post.attributes).valid?
=> false

I'd expect the return values of valid? and new_record? to remain the same after the import.

I'm using Rails 7.1 with Postgres.

Numie avatar Dec 14 '23 22:12 Numie

Running in to the same problem. Using Rails 5 did you figure out a reason or fix for this ?

veeKewl avatar Jan 16 '24 19:01 veeKewl

Running in to the same problem. Using Rails 5 did you figure out a reason or fix for this ?

No, awaiting any feedback

Numie avatar Jan 17 '24 19:01 Numie

It seems post is being hydrated from a database record. Can you determine which record it is loading from the database by inspecting the id? I wonder if the recursive option is mistakenly populating the object from the database.

jkowens avatar Jan 17 '24 20:01 jkowens

It seems post is being hydrated from a database record. Can you determine which record it is loading from the database by inspecting the id? I wonder if the recursive option is mistakenly populating the object from the database.

post.id
=> nil

So it doesn't seem like a different record is being pulled from the db. Somehow valid? is being overwritten to make a non-persisted and invalid record return true?

Numie avatar Jan 17 '24 20:01 Numie

Strange, I wonder why new_record? is returning false.

jkowens avatar Jan 17 '24 20:01 jkowens

have you tried adding raise_error ?? i tried it and the it showed the error for me. on my case the company is new and not saved yet, the post.valid? was returning true for me because it was actually valid if i just use post.save! it will also save the company first then save the post.

veeKewl avatar Jan 18 '24 02:01 veeKewl

No, I don't want to raise errors, otherwise import! could be used. I just want methods like valid? to return false correctly if the import is unsuccessful.

Numie avatar Jan 23 '24 19:01 Numie