Recent 3.2.9 release bugfix has brought an issue for
through
associations.
inverse_of
usage can solve the problem only partially (polymorphic associations are still affected).
UPDATE: patch that introduced this issue has just been
reverted in rails master.Few days ago Rails 3.2.9 was released. Among the bugfixes a
fix for through
associations is present, and since 3.2.9 join model instances are built even though the object is not saved yet.To get the point take a look at these simple models with
User
and
Team
joined with each other
through
UserMembership
:
class User
Before Rails 3.2.9 this code does not build any UserMembership
instances:
team = Team.new(users: [User.first])
team.valid? #=> true
team.user_memberships #=> []
But since Rails 3.2.9 UserMembership
instance is built:
team = Team.new(users: [User.first])
team.valid? #=> false
team.user_memberships #=> [#]
team.user_memberships.first.team #=> nil
Oh, have you noticed that team
is invalid now? Aahh, now when it get's complicated.Built instance of a join UserMembership
model has no team
set and that's why it's invalid (it has validate :team, :user, presence: true
). As soon as join model instance is invalid team
is invalid as well.To fix this validation issues in this particular case the one should use inverse_of
for the associations like this:
class User :user
has_many :teams, through: :user_memberships
end
class Team :team
has_many :users, through: :user_memberships
end
team = Team.new(users: [User.first])
team.valid? #=> true
team.user_memberships.first.valid? #=> true
team.user_memberships.first.team #=> #
inverse_of
takes care of associations objects in-memory synchronization, so now UserMembership
instance has a team
and it's valid. Unfortunately polymorphic associations are still affected - follow this github discussion for more info.That said, if you've just upgraded to 3.2.9 and your tests are failing review the associations and fix them whenever it's possible by using inverse_of
.