Building and saving has_many and has_one relations

Hi,

I am very confused about an aspect of has_one and has_many relations,
with regard to using the build method, and saving the belongs_to side.
It’s a somewhat long post. so please bear with me :slight_smile:

First let’s consider the has_one scenario. Let’s say I have a student
who must own exactly one car:

class Student
has_one(:car)
end

class Car
belongs_to(:student)
validates_presence_of(:student_id)
end

When I do

student = Student.new(attributes_of_student)
car = student.build_car(attributes_of_car)

The car is created, and I can do:

student.save!
car.save!

I don’t understand why build_car also assigns the car to the student.
According to the docs [1], build is an equivalent, in this case, for:

Car.new(“student_id” => student.id, attributes_of_car)

which does it assign the car to the student. Is that simply a bug in
the docs?

And now comes has_many, which is where the real confusion begins. Take
the same scenario, but now a student can own one or more cars:

class Student
has_many(:cars)
end

class Car
belongs_to(:student)
validates_presence_of(:student_id)
end

When I do

student = Student.new(attributes_of_student)
student.cars.build(attributes_of_car1)
student.cars.build(attributes_of_car2)

Until now, everything is fine, except that the cars are part of the
cars collection of student, which doesn’t happen according to the doc
[2]. The real problem comes when I do

student.save!

It won’t save when there are invalid cars, and the cars are always
invalid, because student_id is still nil: catch 22. Why doesn’t rails
automatically handle the student relation of car here, like it does
for the has_one?

Another problem, is that for the has_one, I have to manually call
“valid?” on car, to be able to see invalid fields in the GUI when the
student also has invalid fields (the call to student.save! aborts the
block so that the car is not checked), but for the has_many, calling
“save!” on student automatically marks all invalid cars, and therefore
also all the fields in the GUI.

I hope somebody is able to alleviate my confusion.

[1]

[2]