在自联接中的两个外键之间搜索的查询 table

query to search between two foreign keys in a self join table

用户中的示例数据 table

rails 控制台中的预期结果,father.childrenmother.children 应该 return 同一组对象:

father = User.first
father.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>
mother = User.find(2)
mother.children
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "son", father_id: 1, mother_id: 2>, #<User id: 4, name: "daughter", father_id: 1, mother_id: 2>]>

这是我现在在 User.rb 模型中的协会。它 return 是我执行 father.children 的预期结果,因为 foreign_key 指的是 father_id。但它不适用于 mother.children 因为它不引用 mother_id.

 has_many :children, foreign_key: "father_id", class_name: "User"
 belongs_to :mother, class_name: "User", optional: true
 belongs_to :father, class_name: "User", optional: true

我有办法吗

foreign key: "father_id" OR "mother_id"

我也尝试在协会中进行查询,但似乎无法理解它。

 has_many :children, -> { where("father_id = id OR mother_id = id") }, class_name: "User"

您可以取消该查询创建的默认范围,然后使用用户 ID 过滤子行:

has_many :children,
  ->(user) { unscope(:where).where('father_id = :id OR mother_id = :id', id: user.id) },
  class_name: "User"

为什么unscope?如果不删除它,您的代码将导致两个 SQL 查询,如下所示:

SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
SELECT "users".* FROM "users" WHERE "users"."user_id" = ? AND "users"."father_id" = ?  [["user_id", 1], ["father_id", "1"]]

User.first.children 时 - 至少在 Rails 6.1.4.

如您所见,第二个查询过滤了所有 id 等于接收者 (1) 且同时具有 father_id 列等于接收者 (1) 的用户.查看您的代码,这可能永远不会发生。

注意,如果在声明 has_many 关系后您真的不需要将所有这些方法添加到模型中,您最好使用单个实例方法或作用域(在最后一种情况下) .因为使用这种方法,您覆盖了默认行为(无处记录),即通过此行中的主键过滤其他 table 中的行。