has_one and has_many associations: which side of the association is saved first
Posted
by SeeBees
on Stack Overflow
See other posts from Stack Overflow
or by SeeBees
Published on 2010-04-20T03:20:14Z
Indexed on
2010/04/20
3:23 UTC
Read the original article
Hit count: 323
ruby-on-rails
|activerecord
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.
© Stack Overflow or respective owner