Ruby on rails Rails-查找没有特定类型关联记录的记录

Ruby on rails Rails-查找没有特定类型关联记录的记录,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我有三种型号: class Person < ActiveRecord::Base has_many :assignments has_many :projects, through: :assignments end class Project < ActiveRecord::Base has_many :assignments has_many :people, through: :assignments end class Assignment < A

我有三种型号:

class Person < ActiveRecord::Base
  has_many :assignments
  has_many :projects, through: :assignments
end

class Project < ActiveRecord::Base
  has_many :assignments
  has_many :people, through: :assignments
end

class Assignment < ActiveRecord::Base
  belongs_to :person
  belongs_to :project
end

如何编写与上述示例相反的内容,并找到没有指定工作人员的项目?

如果您使用的是Rails 4.0+,则可以否定上述内容:

joins(:assignments).where.not(assignments: { :kind => 'worker' })

这将为您提供所有未分配工作人员的项目。

如果您使用的是Rails 4.0+,则可以取消上述项目:

class Project < ActiveRecord::Base
  def self.assigned_workers
    joins(:assignments).where(assignments: { :kind => 'worker' })
  end
end
joins(:assignments).where.not(assignments: { :kind => 'worker' })

这将为您提供所有未分配工作人员的项目。

我想您需要一个左联接。不幸的是,Rails并没有让这变得容易。但您仍然可以使用SQL片段:

class Project < ActiveRecord::Base
  def self.assigned_workers
    joins(:assignments).where(assignments: { :kind => 'worker' })
  end
end
joins("LEFT JOIN assignments ON assignments.project_id = projects.id AND assignments.kind = 'worker'").where(assignments: {id: nil})

因此,SQL在赋值类型为“worker”的赋值上执行左联接,但只选择没有匹配赋值的行。

我想您需要左联接。不幸的是,Rails并没有让这变得容易。但您仍然可以使用SQL片段:

joins("LEFT JOIN assignments ON assignments.project_id = projects.id AND assignments.kind = 'worker'").where(assignments: {id: nil})

因此,SQL在工作分配类型为“worker”的工作分配上执行左联接,但只选择没有匹配工作分配的行。

这种方法不只是选择分配了其他人的项目吗?即使一个项目没有分配工人,它仍然可以有一个主管或检查员。它将接受所有分配了非工人类型的工作的项目。>即使一个项目没有分配工人,你能给我一个有工人分配的项目的例子吗?这种方法不只是选择分配了其他人的项目吗?即使一个项目没有分配工人,它仍然可以有一个主管或检查员。它将接受所有分配了非工人类型的工作的项目。>即使一个项目没有分配工人,你能给我一个分配工人的项目的例子吗?谢谢Andrew,这种方法会比运行一个不在查询更好吗
where.not(id:assigned\u workers.pull(:id))
我更喜欢它,因为它可以在单个查询中完成。在这里的示例中,assigned_workers.pull(:id)运行第一个查询,其结果将用于第二个查询。单一查询的另一个优点是更容易将其转换为关联:
有许多:分配的非工作者,->{},类名:“Person”
。这允许您现在使用Project.joins(:assigned\u non\u workers),这非常酷。如果提取与特定实例相关的ID,则无法执行此操作。很抱歉,由于:至,关联定义需要工作,但我在注释上的编辑时间已用完。但这在某些工作中是绝对可能的。我认为您可以在分配上定义关联类型:
has\u many:non\u workers,->{},类名:“Person”
,然后在项目中使用
has\u many:assigned\u non\u workers,通过::assignments,source::non\u workers
,类似地,您可能会考虑将AssociigdSeWork方法更改为关联,这是更容易的:赋值<代码> HasyMule:工人,{“类”:“工人”},类名字:“人”,Project <代码> HasyMul众多:工作者,通过::作业,来源::工人< /代码>(我不认为您需要此关联的
:class\u name
,但我不是100%确定。谢谢Andrew,这种方法会比运行不在查询好吗?
where.not(id:assigned\u workers.pull(:id))
我更喜欢它,因为它可以在单个查询中执行。在您的示例中,assigned\u workers.pull(:id)运行第一个查询,其结果在第二个查询中使用。单个查询的另一个优点是更容易将其转换为关联:
有许多:已分配的非工作人员,->{},类名:“Person”
。这允许您现在使用Project.joins(:已分配的非工作人员),这很酷。如果您提取与特定实例相关的ID,则无法执行此操作。很抱歉,由于:至,关联定义需要工作,但我在注释上的编辑时间已用完。但通过一些工作,这是绝对可能的。我想您可以在赋值时定义关联类型:
有许多:非工作者,->{类名称:“人”<代码>,然后使用在Project <代码> HasyMult:AssociigdNoNoWork,通过::赋值,源::NoWorksWorks/Cuth>类似地,您可以考虑将AssociigdWorkWork方法更改为关联,这是更容易的:赋值<代码> HasyMult:工人,{“类”:“工作者”},类名字:“人”
,项目
有很多:工人,通过::分配,源::工人
(我不相信你需要
:这个关联的类名
,但我不是100%确定。