我试图使用where查询与关系。
在这种情况下,如何使用带关系的where查询?
这是模型
User
has_many :projects
has_many :reasons, through: :projects
Project
belongs_to :user
has_many :reasons
Reasons
belongs_to :project
这是不起作用的密码
# GET /reasons
def index
reasons = current_user.reasons
updated_at = params[:updated_at]
# Filter with updated_at for reloading from mobile app
if updated_at.present?
# This one doesn't work!!!!!!!!!!!!
reasons = reasons.includes(:projects).where("updated_at > ?", Time.at(updated_at.to_i))
# Get all non deleted objects when logging in from mobile app
else
reasons = reasons.where(deleted: false)
end
render json: reasons
end
-最新消息
谢谢@AmitA,这是正确的。
reasons = reasons.joins(:project).where("projects.updated_at > ?", Time.at(updated_at.to_i))
发布于 2016-04-29 17:18:46
如果要查询其项目具有某些约束的所有原因,则需要使用joins
而不是includes
。
reasons = reasons.joins(:project).where("projects.updated_at > ?", Time.at(updated_at.to_i))
请注意,当includes
和joins
都收到一个符号时,它们会查找具有该精确名称的关联。这就是为什么您不能实际执行includes(:projects)
,但必须执行includes(:project)
或joins(:project)
。
还请注意,where
指定的连接表的约束必须引用表名,而不是关联名称。这就是为什么我使用projects.updated_at
(复数)而不是其他任何东西的原因。换句话说,当调用where
方法时,您处于"SQL域中“。
includes
和joins
是有区别的。includes
运行一个单独的查询来加载依赖项,然后将它们填充到获取的活动记录对象中。所以:
reasons = Reason.where('id IN (1, 2, 3)').includes(:project)
将做以下工作:
SELECT * FROM reasons WHERE id IN (1,2,3)
,并为每个记录构造ActiveRecord对象Reason
。SELECT * FROM projects WHERE id IN (11,12,13)
并为每个记录构造ActiveRecord对象Project
。Reason
ActiveRecord对象的ActiveRecord关联。以上最后一步意味着您可以安全地完成以下操作:
reasons.first.project
并且不会启动任何查询来获取第一个原因的项目。这就是为什么使用includes
来解决N+1查询的原因。但是,请注意,SQL中没有JOIN子句--它们是单独的SQL。因此,在使用includes
时不能添加SQL约束。
这就是joins
进来的原因。它只是将表连接起来,这样就可以在已连接的表上添加where
约束。但是,它并没有为您预先填充关联。实际上,Reason.joins(:project)
永远不会实例化Project
ActiveRecord对象。
如果要同时执行joins
和includes
,可以使用第三个方法eager_load
。您可以阅读更多关于差异的这里。
https://stackoverflow.com/questions/36949647
复制相似问题