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

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

用户表中的数据示例

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

  1. grandfather = User.first
  2. grandfather.grandchildren
  3. => #<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>]>
  4. grandmother = User.find(2)
  5. grandmother.grandchildren
  6. => #<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模型中的关联。

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

现在在rails控制台中输出:

  1. irb(main):001:0> grandfather = User.first
  2. (0.3ms) SELECT sqlite_version(*)
  3. User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
  4. => #<User id: 1, name: "grandfather", mother_id: nil, father_id: nil>
  5. irb(main):002:0> grandfather.grandchildren
  6. 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]]
  7. Traceback (most recent call last):
  8. ActiveRecord::StatementInvalid (SQLite3::SQLException: ambiguous column name: father_id)
snz8szmq

snz8szmq1#

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

  1. SELECT "users".*
  2. FROM "users"
  3. INNER JOIN "users" "children_grandchildren"
  4. ON "users"."user_id" = "children_grandchildren"."id"
  5. 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:

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

相关问题