I have something like the following:
class Project < ActiveRecord::Base
has_many :project_people
has_many :people, :through => :project_people
end
class Person < ActiveRecord::Base
has_many :project_people
has_many :projects, :through => :project_people
end
class ProjectPerson < ActiveRecord::Base
belongs_to :project
belongs_to :person
scope :lead, where(:is_lead => true)
scope :member, where(:is_lead => false)
end
When adding a "lead" ProjectPerson to a new Project, it appears to build correctly, but when calling "@project.project_people" the array is empty:
@project = Project.new
=> #<Project id: nil, name: nil>
@project.project_people.lead.build
=> #<ProjectPerson id: nil, project_id: nil, person_id: nil, is_lead: true>
@project.project_people
=> []
When I try this without the scope, the ProjectPerson shows up in the array:
@project.project_people.build
=> #<ProjectPerson id: nil, project_id: nil, person_id: nil, is_lead: false>
@project.project_people
=> [#<ProjectPerson id: nil, project_id: nil, person_id: nil, is_lead: false>]
How can I get it so that built scoped association records are also included?
UPDATE: This is an old question that's recently gained some attention. Originally I included a simple example of two scopes that use a boolean. A couple of the recent answers (Feb 2014) have focused on my specific examples instead of the actual question. My question was not for the "lead" and "member" scopes specifically (sometimes scopes are a lot more complex than this), but rather, if it's possible to use a scope and then the build
method on an ActiveRecord model. I'm hoping I'm wrong, but there currently doesn't seem to be support for this.
TLDR: Build won't add the built lead to the association until you actually save the built lead.
I've made a simple rails app with the associations for you to check out if you're curious using rails 4.0. https://github.com/TalkativeTree/challenges-learning/tree/master/scope_has_many
In my opinion, I think Member would be a better name that ProjectPerson. That way you could just do Project.first.members
and Project.first.members.lead
. If you want a project's non-lead members, you could do Project.first.members.where(is_lead: false)
Models:
class Member < ActiveRecord::Base
belongs_to :project
belongs_to :person
scope :lead, -> { where(is_lead: true) }
end
class Project < ActiveRecord::Base
has_many :members
has_many :people, through: :members
end
class Person < ActiveRecord::Base
has_many :members
has_many :projects, through: :members
end
and how to create the lead.
> p = Project.new
=> #<Project id: nil, created_at: nil, updated_at: nil>
> p.save
=> true
> p.members
=> []
> p.members.lead.create
=> #<Member id: 1, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:18:59", updated_at: "2014-02-16 06:18:59">
> p
=> #<Project id: 1, created_at: "2014-02-16 06:18:51", updated_at: "2014-02-16 06:18:51">
> p.members.create
=> #<Member id: 2, is_lead: false, person_id: nil, project_id: 1, created_at: "2014-02-16 06:19:07", updated_at: "2014-02-16 06:19:07">
> p.members
=> [#<Member id: 2, is_lead: false, person_id: nil, project_id: 1, created_at: "2014-02-16 06:19:07", updated_at: "2014-02-16 06:19:07">]
Build won't update the association until you actually save the association.
> l = p.members.lead.build
=> #<Member id: nil, is_lead: true, person_id: nil, project_id: 1, created_at: nil, updated_at: nil>
> l
=> #<Member id: nil, is_lead: true, person_id: nil, project_id: 1, created_at: nil, updated_at: nil>
> l.save
=> true
> p.members.lead
=> [#<Member id: 1, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:18:59", updated_at: "2014-02-16 06:18:59">,
#<Member id: 3, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:23:04", updated_at: "2014-02-16 06:23:04">]
> l2 = p.members.lead.build
=> #<Member id: nil, is_lead: true, person_id: nil, project_id: 1, created_at: nil, updated_at: nil>
> p.members.lead
=> [#<Member id: 1, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:18:59", updated_at: "2014-02-16 06:18:59">,
#<Member id: 3, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:23:04", updated_at: "2014-02-16 06:23:04">]
> l2.save
=> true
> p.members.lead
=> [#<Member id: 1, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:18:59", updated_at: "2014-02-16 06:18:59">,
#<Member id: 3, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:23:04", updated_at: "2014-02-16 06:23:04">,
#<Member id: 4, is_lead: true, person_id: nil, project_id: 1, created_at: "2014-02-16 06:23:34", updated_at: "2014-02-16 06:23:34">]
Also, if your data isn't showing for p
, trying reloading the model will reflect the changes to the database.
> p
=> #<Project id: 2, created_at: "2014-02-14 03:21:55", updated_at: "2014-02-14 03:21:55">
> p.members
=> []
> p.reload
=> #<Project id: 2, created_at: "2014-02-14 03:21:55", updated_at: "2014-02-14 03:21:55">
> p.members
=> [#<Member id: 6, is_lead: true, person_id: nil, project_id: 2, created_at: "2014-02-14 03:22:24", updated_at: "2014-02-14 03:22:24">]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With