has_many through association on unsaved objects

42 views
Skip to first unread message

Markus D.

unread,
Oct 30, 2014, 1:56:51 PM10/30/14
to rubyonra...@googlegroups.com
Hello,

I just stumbled upon a behaviour about associations I do not really understand why Rails/ActiveRecord cannot get the connection. Using activerecord (4.2.0.beta2).

To describe it, lets work with theses models:

class User < ActiveRecord::Base
    has_many
:project_participations
    has_many
:projects, through: :project_participations, inverse_of: :users
end

class ProjectParticipation < ActiveRecord::Base
    belongs_to
:user
    belongs_to
:project

   
enum role: { member: 0, manager: 1 }
end

class Project < ActiveRecord::Base
    has_many
:project_participations
    has_many
:users, through: :project_participations, inverse_of: :projects
end

A user can participate in many projects with a role as a member or a manager. The connecting model is called ProjectParticipation.

I now have a problem using the associations on unsaved objects. The following commands work like I think they should work:

# first example

u
= User.new
p
= Project.new

u
.projects << p

u
.projects
=> #<ActiveRecord::Associations::CollectionProxy [#<Project id: nil>]>

u
.project_participations
=> #<ActiveRecord::Associations::CollectionProxy [#<ProjectParticipation id: nil, user_id: nil, project_id: nil, role: nil>]>

So far so good - AR created the ProjectParticipation by itself and I can access the projects of a user with u.projects.

But it does not work if I create the ProjectParticipation by myself:

# second example

u
= User.new
pp
= ProjectParticipation.new
p
= Project.new

pp
.project = p # assign project to project_participation

u
.project_participations << pp # assign project_participation to user

u
.project_participations
=> #<ActiveRecord::Associations::CollectionProxy [#<ProjectParticipation id: nil, user_id: nil, project_id: nil, role: nil>]>

u
.projects
=> #<ActiveRecord::Associations::CollectionProxy []>

Why are the projects empty? I cannot access the projects by u.projects like before, even the ProjectParticipation is there.

But if I go through the participations directly, the project shows up:

u.project_participations.map(&:project)
=> [#<Project id: nil>]

Shouldn't it work like the first example directly:
u.projects returning me all projects not depending on whether I create the join object by myself or not? Or how can I make AR aware of this?

Matt Jones

unread,
Oct 31, 2014, 10:37:59 AM10/31/14
to rubyonra...@googlegroups.com
`u.projects` is going to load things from the database if the record is saved, but otherwise it will only return objects you've explicitly stored in it.

The `through` association is not the same as just mapping `&:project` over project_participations.

Can you describe what you're trying to do in more detail? There's likely a way to make AR do the right thing.

--Matt Jones 
Reply all
Reply to author
Forward
0 new messages