在Rails中如何构建具有范围的has_many关联

rob*_*ord 9 scope ruby-on-rails build has-many

我有以下内容:

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
Run Code Online (Sandbox Code Playgroud)

将"引导"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
 => []
Run Code Online (Sandbox Code Playgroud)

当我在没有范围的情况下尝试此操作时,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>]
Run Code Online (Sandbox Code Playgroud)

如何获取它以便还包括构建的作用域关联记录?

更新:这是一个老问题,最近引起了一些关注.最初我包含了一个使用布尔值的两个范围的简单示例.最近的几个答案(2014年2月)专注于我的具体例子,而不是实际的问题.我的问题不是专门用于"引导"和"成员"范围(有时范围比这要复杂得多),而是,如果可以build在ActiveRecord模型上使用范围然后使用方法.我希望我错了,但目前似乎没有对此表示支持.

Tal*_*ree 5

TLDR:在您实际保存构建的潜在客户之前,Build不会将建立的潜在客户添加到关联.

我已经制作了一个简单的rails应用程序,你可以查看你是否对使用rails 4.0感到好奇.https://github.com/TalkativeTree/challenges-learning/tree/master/scope_has_many

在我看来,我认为会员将是ProjectPerson更好的名字.这样,你可能只是做Project.first.membersProject.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
Run Code Online (Sandbox Code Playgroud)

以及如何创建领导者.

> 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">]
Run Code Online (Sandbox Code Playgroud)

在您实际保存关联之前,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">]
Run Code Online (Sandbox Code Playgroud)

此外,如果您的数据没有显示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">]
Run Code Online (Sandbox Code Playgroud)


Wuk*_*ank 1

我不认为范围和构建应该一起工作。范围用于搜索,构建用于构建/创建新的关联记录。

# this should do the trick
@project.project_people.build(:is_lead=>true)
Run Code Online (Sandbox Code Playgroud)