Table has_many 中的名称通过关系
Table name in has_many through relation
我有一个模型,其中有一对夫妇通过关联寻找兄弟姐妹,即具有相同父项但不是其自身的记录。
class Person
has_many :siblings, -> { where("being_siblings.id != beings.id") }, through: :beings, source: :self_and_related_beings
has_many :nice_humans, through: :siblings, source: :human
end
我的问题是,如果我 运行 person.nice_humans
查询使用的连接 table 的名称与我时不同(在本例中类似于 being_nice_humans
) 运行 person.siblings
在这种情况下它被称为 being_siblings
。有什么方法可以告诉 rails 将 table 别名为什么或以其他方式使它起作用?
我已经尝试过类似 -> (p) { where.not("beings.id = ?", p.id) }
的方法,但我需要在 includes
中使用它,这在我传入实例时是不允许的。
注意:我的例子是基于一个真实的应用程序,但我有关联的名称。
非常感谢任何帮助!
您实际上无法定义这样的关联,因为关联的定义是 class 而不是实例级别。
虽然您可以使用 lambda 向关联添加默认范围,但 lambda 不接受参数,因为在加入、包括或急切加载关联时无法传递这些参数。 self
在 lambda 内部是一个关联代理而不是记录本身,所以你不能写 ->{ where.not(id: self.id) }
.
你能做的就是写一个实例方法:
class Person < ApplicationRecord
belongs_to :parent, optional: :true,
class_name: 'Person'
has_many :siblings, class_name: 'Person',
foreign_key: :parent_id,
primary_key: :parent_id
def siblings
# super is the getter created by the association
super.where.not(id: self.id)
end
end
用法示例:
irb(main):001:0> Person.all
Person Load (0.2ms) SELECT "people".* FROM "people" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Person id: 1, name: "Odin", parent_id: nil, created_at: "2021-01-05 20:36:23", updated_at: "2021-01-05 20:36:23">, #<Person id: 2, name: "Thor", parent_id: 1, created_at: "2021-01-05 20:37:51", updated_at: "2021-01-05 20:37:51">, #<Person id: 3, name: "Balder", parent_id: 1, created_at: "2021-01-05 20:38:56", updated_at: "2021-01-05 20:38:56">]>
irb(main):002:0> Person.last.siblings
Person Load (0.2ms) SELECT "people".* FROM "people" ORDER BY "people"."id" DESC LIMIT ? [["LIMIT", 1]]
Person Load (0.2ms) SELECT "people".* FROM "people" WHERE "people"."parent_id" = ? AND "people"."id" != ? LIMIT ? [["parent_id", 1], ["id", 3], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation [#<Person id: 2, name: "Thor", parent_id: 1, created_at: "2021-01-05 20:37:51", updated_at: "2021-01-05 20:37:51">]>
我有一个模型,其中有一对夫妇通过关联寻找兄弟姐妹,即具有相同父项但不是其自身的记录。
class Person
has_many :siblings, -> { where("being_siblings.id != beings.id") }, through: :beings, source: :self_and_related_beings
has_many :nice_humans, through: :siblings, source: :human
end
我的问题是,如果我 运行 person.nice_humans
查询使用的连接 table 的名称与我时不同(在本例中类似于 being_nice_humans
) 运行 person.siblings
在这种情况下它被称为 being_siblings
。有什么方法可以告诉 rails 将 table 别名为什么或以其他方式使它起作用?
我已经尝试过类似 -> (p) { where.not("beings.id = ?", p.id) }
的方法,但我需要在 includes
中使用它,这在我传入实例时是不允许的。
注意:我的例子是基于一个真实的应用程序,但我有关联的名称。
非常感谢任何帮助!
您实际上无法定义这样的关联,因为关联的定义是 class 而不是实例级别。
虽然您可以使用 lambda 向关联添加默认范围,但 lambda 不接受参数,因为在加入、包括或急切加载关联时无法传递这些参数。 self
在 lambda 内部是一个关联代理而不是记录本身,所以你不能写 ->{ where.not(id: self.id) }
.
你能做的就是写一个实例方法:
class Person < ApplicationRecord
belongs_to :parent, optional: :true,
class_name: 'Person'
has_many :siblings, class_name: 'Person',
foreign_key: :parent_id,
primary_key: :parent_id
def siblings
# super is the getter created by the association
super.where.not(id: self.id)
end
end
用法示例:
irb(main):001:0> Person.all
Person Load (0.2ms) SELECT "people".* FROM "people" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Person id: 1, name: "Odin", parent_id: nil, created_at: "2021-01-05 20:36:23", updated_at: "2021-01-05 20:36:23">, #<Person id: 2, name: "Thor", parent_id: 1, created_at: "2021-01-05 20:37:51", updated_at: "2021-01-05 20:37:51">, #<Person id: 3, name: "Balder", parent_id: 1, created_at: "2021-01-05 20:38:56", updated_at: "2021-01-05 20:38:56">]>
irb(main):002:0> Person.last.siblings
Person Load (0.2ms) SELECT "people".* FROM "people" ORDER BY "people"."id" DESC LIMIT ? [["LIMIT", 1]]
Person Load (0.2ms) SELECT "people".* FROM "people" WHERE "people"."parent_id" = ? AND "people"."id" != ? LIMIT ? [["parent_id", 1], ["id", 3], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation [#<Person id: 2, name: "Thor", parent_id: 1, created_at: "2021-01-05 20:37:51", updated_at: "2021-01-05 20:37:51">]>