rails/rails — Issue #3450: Associations with :validate => true are validating stale associations
Author: janv
Created: 2011-10-27 11:02:14+00:00
State: open

I have two models that looks like this (reduced to the parts relevant to this example):

```ruby
class Car < ActiveRecord::Base
belongs_to :model
validates_presence_of :model_id
end

class Repair < ActiveRecord::Base
belongs_to :car, :validate => true

def new_car_attributes=(attributes)
self.car ||= @new_car = Car.new(attributes)
end

def new_car
@new_car || Car.new(:owner_id => customer_id)
end
end
```

I am creating a repair like this:

```ruby
customer = FactoryGirl.create(:customer)
car = FactoryGirl.create(:car, :owner => customer)

params= {"repair"=>{
"new_car_attributes"=>{
"manufacturer_id"=>"", "owner_id"=>customer.id, :kilometers => 123456},
"car_id"=>car.id}}
repair = Repair.new(params["repair"])
```

Now, if I try to save the repair,it fails because "Car is invalid".
Reason for this is, that the validation validates the new car (with invalid attributes, missing `model_id`).

### Expected behavior:

- Assignment to `car_id` puts the association in a stale state. Trying to access `repair.car` loads the correct car (the one with the id that I assigned to `car_id`)
- The validation of the association also recgnizes this (should happen naturally/automatically) and loads the correct car

### Actual behavior

- The validation of the association does not recognize that the current target of the association is stale and tries to validate the car that is currently stored there, the invalid one that was created by the new_car_attributes setter

If I access `#car` first and validate the Repair afterwards, everything is fine because the accessor has updated the tar of the association reflection to the correct car.

The blame is to be put somewhere here:

```ruby
# activerecord-3.1.1/lib/active_record/autosave_association.rb: 263

# Validate the association if :validate or :autosave is
# turned on for the association.
def validate_single_association(reflection)
association = association_instance_get(reflection.name)
record = association && association.target
association_valid?(reflection, record) if record
end
```

The record that is validated here is obviously not the same I would get if I called the association accessor on the Model (`repair.car` in our example)
This should fix it for this simple case ( a similar change would need to be made in `AutosaveAssociation#associated_records_to_validate_or_save`).

```ruby
def validate_single_association(reflection)
association = association_instance_get(reflection.name)
record = association && association.read
association_valid?(reflection, record) if record
end
```