我有以下内容:
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
将“引导”ProjectPerson添加到新项目时,它似乎构建正确,但在调用“@ project.project_people”时,数组为空:
@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
=> []
当我在没有范围的情况下尝试此操作时,ProjectPerson将显示在数组中:
@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>]
如何获取它以便包含构建的范围关联记录?
更新:这是一个老问题,最近引起了一些关注。最初我包含了一个使用布尔值的两个范围的简单示例。最近的几个答案(2014年2月)专注于我的具体例子,而不是实际的问题。我的问题不是专门用于“引导”和“成员”范围(有时范围比这要复杂得多),而是,如果可以在ActiveRecord模型上使用范围然后使用build
方法。我希望我错了,但目前似乎没有对此表示支持。
答案 0 :(得分:5)
TLDR:在您实际保存构建的潜在客户之前,Build不会将建立的潜在客户添加到关联。
我已经制作了一个简单的rails应用程序,您可以查看是否对使用rails 4.0感到好奇。 https://github.com/TalkativeTree/challenges-learning/tree/master/scope_has_many
在我看来,我认为会员将是ProjectPerson更好的名字。这样你就可以Project.first.members
和Project.first.members.lead
。如果您想要一个项目的非主要成员,您可以Project.first.members.where(is_lead: false)
型号:
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
以及如何创建潜在客户。
> 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不会更新关联。
> 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">]
此外,如果您的数据未显示p
,则尝试重新加载模型将反映对数据库的更改。
> 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">]
答案 1 :(得分:2)
您可以这样做,但它往往会在您的模型上产生许多关联。
如果您正在使用Rails 3(请参阅Rails 4版本更远):
class PeopleProject < ActiveRecord::Base
belongs_to :project
belongs_to :person
scope :lead, -> { where(is_lead: true) }
scope :member, -> { where(is_lead: false)}
end
class Project < ActiveRecord::Base
has_many :people_projects_as_lead, conditions: { is_lead: true }, class_name: 'PeopleProject'
has_many :people_projects_as_member, conditions: { is_lead: false }, class_name: 'PeopleProject'
has_many :leads, through: :people_projects_as_lead, source: :person
has_many :members, through: :people_projects_as_member, source: :person
has_many :people_projects
has_many :people, through: :people_projects
end
class Person < ActiveRecord::Base
has_many :people_projects_as_lead, conditions: { is_lead: true }, class_name: 'PeopleProject'
has_many :people_projects_as_member, conditions: { is_lead: false }, class_name: 'PeopleProject'
has_many :lead_projects, through: :people_projects_as_lead, source: :project
has_many :member_projects, through: :people_projects_as_member, source: :project
has_many :people_projects
has_many :projects, through: :people_projects
end
通过此设置,执行@project.people_projects_as_lead.build
将执行您期望的操作。附加关联名称是否增加清晰度或删除它几乎取决于您的问题域。
上面conditions
与范围之间的重复并不是那么好。 Rails 4可以避免重复的条件:
class Project < ActiveRecord::Base
has_many :people_projects_as_lead, -> { lead }, class_name: 'PeopleProject'
has_many :people_projects_as_member, -> { member }, class_name: 'PeopleProject'
has_many :leads, through: :people_projects_as_lead, source: :person
has_many :members, through: :people_projects_as_member, source: :person
has_many :people_projects
has_many :people, through: :people_projects
end
class Person < ActiveRecord::Base
has_many :people_projects_as_lead, -> { lead }, class_name: 'PeopleProject'
has_many :people_projects_as_member, -> { member }, class_name 'PeopleProject'
has_many :lead_projects, through: :people_projects_as_lead, source: :project
has_many :member_projects, through: :people_projects_as_member, source: :project
has_many :people_projects
has_many :projects, through: :people_projects
end
注意:您可能需要其他inverse_of
个选项,以确保所有内容都能正确保存,尤其是Project
/ Person
和PeopleProject
之间的关系。如果使用此代码正确设置了所有内容,您将能够执行@project.leads << some_person
之类的操作并正确构建连接记录。
答案 2 :(得分:1)
我不认为范围和构建是为了协同工作。范围用于搜索和构建是用于构建/创建新的关联记录。
# this should do the trick
@project.project_people.build(:is_lead=>true)