rails ruby 中 child 的 child 协会
Association for the child of the child in ruby on rails
用户中的数据示例 table
rails 控制台中的预期结果,grandfather.grandchildren
和 grandmother.grandchildren
应该 return 同一组 objects:
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)
你不能通过 children 从祖父母那里得到祖父母的祖父母 children 因为这意味着他们的 father/mother id 等于祖父母,它不穿越盛大childrenparents:
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到grandchildren关系,类似于children
的关系,但是这次提取祖父母[=21] =] ids,并使用 IN 子句过滤那些匹配这些 ids 的用户行,他们的 father/mother ids:
has_many :grandchildren,
->(user) { unscope(:where).where('father_id IN (:ids) OR mother_id IN (:ids)', ids: user.children.ids) },
class_name: "User"
用户中的数据示例 table
rails 控制台中的预期结果,grandfather.grandchildren
和 grandmother.grandchildren
应该 return 同一组 objects:
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)
你不能通过 children 从祖父母那里得到祖父母的祖父母 children 因为这意味着他们的 father/mother id 等于祖父母,它不穿越盛大childrenparents:
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到grandchildren关系,类似于children
的关系,但是这次提取祖父母[=21] =] ids,并使用 IN 子句过滤那些匹配这些 ids 的用户行,他们的 father/mother ids:
has_many :grandchildren,
->(user) { unscope(:where).where('father_id IN (:ids) OR mother_id IN (:ids)', ids: user.children.ids) },
class_name: "User"