我不知道如何使用.where()
方法来检索关联的模型数据。在此示例中,项目belongs_to用户...
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}
(来手动添加它,但这感觉不像"The Rails Way"。什么?
溶液我最初的问题是在错误的假设下制定的,即debug()
会返回相关的对象(这在 cakePHP 中有效,因为它将所有内容捆绑到数组中(。
所以我的原始代码应该可以工作。但是,我错误地命名了表中归档的外键。我在查看迁移方法t.belongs_to
时感到困惑(它会自动创建正确命名的foreign_key字段,而不是名为"belongs_to"的字段(。所以我还必须将该列重命名为 user_id
,现在它的工作原理就像下面 @Veraticus 的答案中所述。
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
查询更为重要,其中急切加载关联可以保存 N+1 个数据库查询。
您可以通过在预先加载后的某个时间点调用@project.user
并检查日志来验证这是否正常工作:您应该看到当时没有数据库调用。
预先加载,N+1 查询优化实际上是在单个调用中加载关联的有效方法。
- include(( 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, ....]}]