将 SQL 查询从关联切换到实例方法
Switching SQL queries from association into instance methods
我现在的User.rb模特
class User < ApplicationRecord
has_many :children,
-> (user) { unscope(:where).where("father_id = :id OR mother_id = :id", id: user.id) },
class_name: "User"
has_many :grandchildren,
-> (user) { unscope(:where).where("father_id IN (:ids) OR mother_id IN (:ids)", ids: user.children.ids) },
class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
end
我目前的数据(空的为nil):
所有查询现在都有效:
但是对于 .grandchildren
查询,您可以看到在控制台中创建了三个(两个重复查询)查询。有没有办法只生成一个查询?
我正在尝试实例方法,因为我可以输入原始 SQL,但似乎无法理解它。一个例子:
def children
sql = ("SELECT users.* FROM users WHERE (father_id = id OR mother_id = id)")
p ActiveRecord::Base.connection.execute(sql)
end
最终目标:
- 执行
.grandchildren
时生成一个查询
你可以替换
-> (user) { unscope(:where).where("father_id IN (:ids) OR mother_id IN (:ids)", ids: user.children.ids) },
有
-> (user) do
scope = unscope(:where)
children_ids = user.children.select(:id)
scope
.where(father_id: children_ids)
.or(scope.where(mother_id: children_ids))
end
解决了
has_many :children,
-> (user) { unscope(:where).where("father_id = :id OR mother_id = :id", id: user.id) },
class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
def grandchildren
user_id = self.id
User.where(
"father_id IN (:ids) OR mother_id IN (:ids)",
ids: User.where("father_id = :id OR mother_id = :id", id: user_id).pluck(:id)
)
end
我现在的User.rb模特
class User < ApplicationRecord
has_many :children,
-> (user) { unscope(:where).where("father_id = :id OR mother_id = :id", id: user.id) },
class_name: "User"
has_many :grandchildren,
-> (user) { unscope(:where).where("father_id IN (:ids) OR mother_id IN (:ids)", ids: user.children.ids) },
class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
end
我目前的数据(空的为nil):
所有查询现在都有效:
但是对于 .grandchildren
查询,您可以看到在控制台中创建了三个(两个重复查询)查询。有没有办法只生成一个查询?
我正在尝试实例方法,因为我可以输入原始 SQL,但似乎无法理解它。一个例子:
def children
sql = ("SELECT users.* FROM users WHERE (father_id = id OR mother_id = id)")
p ActiveRecord::Base.connection.execute(sql)
end
最终目标:
- 执行
.grandchildren
时生成一个查询
你可以替换
-> (user) { unscope(:where).where("father_id IN (:ids) OR mother_id IN (:ids)", ids: user.children.ids) },
有
-> (user) do
scope = unscope(:where)
children_ids = user.children.select(:id)
scope
.where(father_id: children_ids)
.or(scope.where(mother_id: children_ids))
end
解决了
has_many :children,
-> (user) { unscope(:where).where("father_id = :id OR mother_id = :id", id: user.id) },
class_name: "User"
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
def grandchildren
user_id = self.id
User.where(
"father_id IN (:ids) OR mother_id IN (:ids)",
ids: User.where("father_id = :id OR mother_id = :id", id: user_id).pluck(:id)
)
end