Rails 查找除已经关联的二级记录之外的所有记录
Rails find all records except already second level associated
我的 rails 应用程序中有以下模型
型号community
:
class Community < ActiveRecord::Base
has_many :community_program
end
型号community_program
:
class CommunityProgram < ActiveRecord::Base
belongs_to :program_name
end
型号program_name
:
class ProgramName < ActiveRecord::Base
has_many :community_programs
end
我正在尝试找到一种方法来提取所有不属于 community_program
的 program_names
,而 community_program
已经分配给了 community
。
我已经能够拉出所有 program_names
,然后删除已经与 community
相关联的 program_names
,但这非常昂贵。可以直接拉取二级无关联记录吗?
编辑:这个问题与链接的问题不同,因为在这种情况下,program_name
可能与不同社区的社区计划有关联,但我们仍然希望包含该名称如果它与当前 community
.
没有关联
**编辑 2:我想提取所有尚未分配给与特定社区关联的社区计划的计划名称。它们可以与不同社区相关联的社区计划相关联。用例是用户应该能够 select 从剩余名称列表中选择一个名称,并将其分配给与其社区关联的社区计划。
程序名称是全球性的,虽然特定社区的社区程序的程序名称是唯一的,但不同的社区可以有与同一程序名称相关联的社区程序**
您可以通过几种不同的方式来执行此操作,具体取决于您在哪个 controller/view 上显示它们。
在社区模型上创建 association:
has_many :unassigned_program_names, -> { where community_program_id: nil }
在 ProgramName 模型上创建这样的 scope:
scope :unassigned, -> { where(community_program_id: nil) }
希望这对您有所帮助。 :)
让except_community
是一个特定的Community
应该排除的关联。下面的代码将产生一个 SQL 查询:
except_relation = except_community.
community_programs.
select(:program_name_id)
ProgramName.
where.not(id: except_relation)
您可以将其添加为 Community
模型的实例方法。
可能是这样的:
class Community < ActiveRecord::Base
has_many :community_programs
end
class CommunityProgram < ActiveRecord::Base
belongs_to :program_name, optional: true
belongs_to :community
end
class ProgramName < ActiveRecord::Base
has_many :community_programs
end
some_community = Community.find some_community_id
programs_from_a_community = some_community.community_programs.map &:id
program_names_to_exclude = CommunityProgram.where(id: programs_from_a_community)
.where.not(program_name_id: nil)
.map { |c_p| c_p.program_name.id }
program_names = ProgramName.where.not(id: program_names_to_exclude)
我之前接受的答案版本被拒绝了,所以我将其添加为另一个答案。 Pavel Mikhailyuk 提供的解决方案解决了我的问题。
因为我想找到最有效的查询,所以我最终更新了它并使用了:
ProgramName.where.not(id: except_community.community_programs.pluck(:program_name_id))
编辑:所选答案比这更有效。
我的 rails 应用程序中有以下模型
型号community
:
class Community < ActiveRecord::Base
has_many :community_program
end
型号community_program
:
class CommunityProgram < ActiveRecord::Base
belongs_to :program_name
end
型号program_name
:
class ProgramName < ActiveRecord::Base
has_many :community_programs
end
我正在尝试找到一种方法来提取所有不属于 community_program
的 program_names
,而 community_program
已经分配给了 community
。
我已经能够拉出所有 program_names
,然后删除已经与 community
相关联的 program_names
,但这非常昂贵。可以直接拉取二级无关联记录吗?
编辑:这个问题与链接的问题不同,因为在这种情况下,program_name
可能与不同社区的社区计划有关联,但我们仍然希望包含该名称如果它与当前 community
.
**编辑 2:我想提取所有尚未分配给与特定社区关联的社区计划的计划名称。它们可以与不同社区相关联的社区计划相关联。用例是用户应该能够 select 从剩余名称列表中选择一个名称,并将其分配给与其社区关联的社区计划。
程序名称是全球性的,虽然特定社区的社区程序的程序名称是唯一的,但不同的社区可以有与同一程序名称相关联的社区程序**
您可以通过几种不同的方式来执行此操作,具体取决于您在哪个 controller/view 上显示它们。
在社区模型上创建 association:
has_many :unassigned_program_names, -> { where community_program_id: nil }
在 ProgramName 模型上创建这样的 scope:
scope :unassigned, -> { where(community_program_id: nil) }
希望这对您有所帮助。 :)
让except_community
是一个特定的Community
应该排除的关联。下面的代码将产生一个 SQL 查询:
except_relation = except_community.
community_programs.
select(:program_name_id)
ProgramName.
where.not(id: except_relation)
您可以将其添加为 Community
模型的实例方法。
可能是这样的:
class Community < ActiveRecord::Base
has_many :community_programs
end
class CommunityProgram < ActiveRecord::Base
belongs_to :program_name, optional: true
belongs_to :community
end
class ProgramName < ActiveRecord::Base
has_many :community_programs
end
some_community = Community.find some_community_id
programs_from_a_community = some_community.community_programs.map &:id
program_names_to_exclude = CommunityProgram.where(id: programs_from_a_community)
.where.not(program_name_id: nil)
.map { |c_p| c_p.program_name.id }
program_names = ProgramName.where.not(id: program_names_to_exclude)
我之前接受的答案版本被拒绝了,所以我将其添加为另一个答案。 Pavel Mikhailyuk 提供的解决方案解决了我的问题。
因为我想找到最有效的查询,所以我最终更新了它并使用了:
ProgramName.where.not(id: except_community.community_programs.pluck(:program_name_id))
编辑:所选答案比这更有效。