sql—RubyonRails中子对象的子对象的关联

klr1opcd  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(302)

用户表中的数据示例

rails控制台中的预期结果, grandfather.grandchildrengrandmother.grandchildren 应返回相同的对象组:

grandfather = User.first
grandfather.grandchildren
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 5, name: "father's son", father_id: 3, mother_id: nil>, #<User id: 6, name: "uncle's son", father_id: 4, mother_id: nil>]>
grandmother = User.find(2)
grandmother.grandchildren
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 5, name: "father's son", father_id: 3, mother_id: nil>, #<User id: 6, name: "uncle's son", father_id: 4, mother_id: nil>]>

这是我现在在user.rb模型中的关联。

has_many :children, ->(user) { unscope(:where).where("father_id = :id OR mother_id = :id", id: user.id) }, class_name: "User"
 has_many :grandchildren, through: :children, source: :children
 belongs_to :mother, class_name: "User", optional: true
 belongs_to :father, class_name: "User", optional: true

现在在rails控制台中输出:

irb(main):001:0> grandfather = User.first
   (0.3ms)  SELECT sqlite_version(*)
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "grandfather", mother_id: nil, father_id: nil>

irb(main):002:0> grandfather.grandchildren
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "users" "children_grandchildren" ON "users"."user_id" = "children_grandchildren"."id" WHERE (father_id = 1 OR mother_id = 1) /* loading for inspect */ LIMIT ?  [["LIMIT", 11]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (SQLite3::SQLException: ambiguous column name: father_id)
snz8szmq

snz8szmq1#

您无法通过祖父母的子女从祖父母那里获得孙辈,因为这意味着他们的父亲/母亲ID与祖父母相同,而不是通过孙辈父母:

SELECT "users".*
FROM "users"
INNER JOIN "users" "children_grandchildren"
ON "users"."user_id" = "children_grandchildren"."id"
WHERE (father_id = 1 OR mother_id = 1) -- this is the grandparent id, when it should be the child parent's id

您可以向孙辈关系添加可调用的,类似于 children ,但这次提取祖父母子女ID,并使用in子句筛选与这些ID匹配的用户行及其父亲/母亲ID:

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

相关问题