has_one and has_many associations: which side of the association is saved first
- by SeeBees
I have three simplified models:
class Team < ActiveRecord::Base
has_many :players
has_one :coach
end
class Player < ActiveRecord::Base
belongs_to :team
validates_presence_of :team_id
end
class Coach < ActiveRecord::Base
belongs_to :team
validates_presence_of :team_id
end
I use the following code to test these models:
t = Team.new
team.coach = Coach.new
team.save!
team.save! returns true.
But in another test:
t = Team.new
team.players << Player.new
team.save!
team.save! gives the following error:
> ActiveRecord::RecordInvalid:
> Validation failed: Players is invalid
> from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/validations.rb:1090:in
> `save_without_dirty!' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/dirty.rb:87:in `save_without_transactions!' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in
> `save!' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in
> `transaction' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:182:in
> `transaction' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in
> `save!' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:208:in
> `rollback_active_record_state!' from
> /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in
> `save!' from (irb):14
I figured out when team.save! is called, it first calls player.save!. player needs to validate the presence of the id of the associated team. But at the time player.save! is called, team hasn't been saved yet, and therefore, team_id doesn't yet exist for player. This fails the player's validation, so the error occurs.
But on the other hand, team is saved before coach.save!, otherwise the first example will get the same error as the second.
So I've concluded that when a has_many bs, a.save! will save bs prior to a. When a has_one b, a.save! will save a prior to b. If I am right, why is this the case? It doesn't seem logical to me. Why has_one and has_many association have different order in saving? Any ideas? Thanks.