红宝石儿童的孩子协会

Posted

技术标签:

【中文标题】红宝石儿童的孩子协会【英文标题】:Association for the child of the child in ruby on rails 【发布时间】:2021-09-25 08:33:50 【问题描述】:

User 表中的数据示例

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)

【问题讨论】:

【参考方案1】:

你不能通过孩子从祖父母那里得到孙子,因为这意味着他们的父亲/母亲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

您可以将 callable 添加到孙子关系中,类似于 children 的关系,但这次提取祖父母子 ID,并使用 IN 子句过滤与那些匹配的用户行ids,以及他们的父亲/母亲 id:

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

【讨论】:

(0.2ms) SELECT "users"."id" FROM "users" WHERE (father_id = 1 OR mother_id = 1) (0.2ms) SELECT "users"."id" FROM "users" WHERE (father_id = 1 OR mother_id = 1) User Load (0.3ms) SELECT "users".* FROM "users" WHERE (father_id IN (3,7) OR mother_id IN (3,7)) /* loading for inspect */ LIMIT ? [["LIMIT", 11]] 出现了三个查询,想知道为什么SELECT "users"."id" FROM "users" WHERE (father_id = 1 OR mother_id = 1) 被查询了两次?是否可以只有一个查询作为输出?答案很有效,谢谢! 是的,我注意到@LeeRenJie,可悲的是,Rails 必须将用户孩子的记录存储在某个地方,所以,可能就是这样。我想,和你之前的问题一样,如果你真的不需要在使用has_many时添加的关系方法,你可以使用一个简单的实例方法。

以上是关于红宝石儿童的孩子协会的主要内容,如果未能解决你的问题,请参考以下文章

巴黎时装周儿童单元深圳站完美落幕

巴黎时装周儿童单元深圳站代言人伊朵,精彩演绎儿童时装

巴黎时装周儿童单元深圳站代言人石雨薇,可爱演绎儿童时尚

巴黎时装周儿童单元上海站圆满举行,徐圣恩受邀参加

徐圣恩受邀出席2022巴黎时装周儿童单元杭州站活动

2022巴黎时装周儿童单元杭州站圆满落幕