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%确定。