我无法弄清楚如何使用.where()
方法来检索关联的模型数据。在此示例中,Projects belongs_to Users ...
class Project < ActiveRecord::Base
belongs_to :user
has_many :videos
end
class User < ActiveRecord::Base
has_many :projects
end
class ProjectsController < ApplicationController
def invite
@project = Project.includes([:user]).where( {:hashed_id=>params[:id]} ).first
end
end
在App / views / projects / invite.html.erg <%= debug( @project ) %>
中返回:
--- !ruby/object:Project
attributes:
id: 22
name: Some Project Name
belongs_to: 1
instructions: Bla bla bla
active: true
max_duration: 2
max_videos:
created_at: 2013-08-26 15:56:50.000000000 Z
updated_at: 2013-08-26 15:56:50.000000000 Z
hashed_id: '1377532589'
不应该将相关的用户哈希/数组包含在其中吗?我知道我可以通过拨打第二个find
/ where
(@project.user = User.where( {:id=>@project.belongs_to}
)来手动添加它,但这并不像&#34; Rails Way&#34;。是什么?
解决方案
我的初始问题是在debug()
将返回关联对象的错误假设下制定的(这在cakePHP中起作用,因为它将所有内容捆绑到数组中)。
所以我原来的代码应该工作。但是,我错误地将表中的外键命名为。通过查看迁移方法t.belongs_to
(自动创建正确命名的foreign_key字段,不名为&#34; belongs_to&#34;的字段),我感到困惑。因此,我还必须将该列重命名为user_id
,现在它的工作方式与@ Veraticus的答案中所述的相同。
答案 0 :(得分:37)
user
对象不属于project
对象,因此您无法在项目中查看它:相反,通过说Project.includes(:user)
,您说的是Rails在找到项目时急切加载引用的关联。这为您节省了数据库通话。例如,非热切地:
@project = Project.where(id: params[:id]).first # one database call, fetching the project
@project.user # another database call, fetching the user
热切地说:
@project = Project.includes(:user).where(id: params[:id]).first # one database call, fetching both project and user
@project.user # no database interaction
这对于has_many
查询更为重要,其中eager-loading关联可以保存N + 1个数据库查询。
您可以在热切加载并检查日志后的某个时刻调用@project.user
来验证这是否正常工作:您应该看到此时没有数据库调用。
答案 1 :(得分:6)
渴望加载,N + 1查询优化实际上是在单个调用中加载关联的有效方式。
- includes()with where()和find()
@project = Project.includes(:user).where(hashed_id: params[:id]).first
@project = Project.where(hashed_id: params[:id]).includes(:user).first
*在某些情况下,它可能很有用*
@projects = Project.find(:all, :includes => :user)
@projects = Project.find(:all, :include => [{:association1 => [:associationA, :associationB, ....]}]