我有很多材料的项目,我正在尝试制作一系列范围来过滤它们:
与论文相关联的project1 。 与塑料
相关联的 project2如果用户点击纸张,我希望显示 project1 和 project2 。如果在第一次查询之后用户点击塑料,我想用新约束过滤第一个查询结果。
换句话说,如果我选择纸张和塑料,我只想显示 project2 。
我的模特:
项目模型
class Project < ApplicationRecord
has_many :project_materials
has_many :materials, through: :project_materials
scope :with_materials, -> (materials) { includes(:materials).where(materials: {id: materials} ) }
end
材料模型:
class Material < ApplicationRecord
has_many :project_materials
has_many :projects, through: :project_materials
end
project_material模型:
class ProjectMaterial < ApplicationRecord
belongs_to :project
belongs_to :material
end
我在rails控制台中尝试了以下内容:
p1 = Project.first
p2 = Project.last
m1 = Material.first
m2 = Material.last
p1.materials << m1
p2.materials << m1
p2.materials << m2
f1 = Project.with_materials(m1)
# which return p1 and p2
f2 = f1.with_materials(m2)
# which return nothings because of the following query
'SQL (1.0ms) SELECT "projects"."id" AS t0_r0, "projects"."name" AS t0_r1, "projects"."difficulty" AS t0_r2, "projects"."status" AS t0_r3, "projects"."duration" AS t0_r4, "projects"."uuid" AS t0_r5, "projects"."slug" AS t0_r6, "projects"."created_at" AS t0_r7, "projects"."updated_at" AS t0_r8, "projects"."project_type_id" AS t0_r9, "materials"."id" AS t1_r0, "materials"."name" AS t1_r1, "materials"."created_at" AS t1_r2, "materials"."updated_at" AS t1_r3 FROM "projects" LEFT OUTER JOIN "project_materials" ON "project_materials"."project_id" = "projects"."id" LEFT OUTER JOIN "materials" ON "materials"."id" = "project_materials"."material_id" WHERE "materials"."id" = 5'
提前谢谢。
答案 0 :(得分:0)
我有一个解决方案可能不是最优雅的,但至少它正在发挥作用。
def self.with_materials materials
materials = [materials].flatten.compact
sql = "SELECT project_id, count(material_id) FROM project_materials WHERE material_id IN (?) GROUP BY project_id HAVING count(material_id) > ?"
ids = ProjectMaterial.find_by_sql [sql, (materials), (materials.count - 1)]
ids.collect!{ |i| i.project_id }
where( id: ids )
end