22

我不知道如何使用该.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}) 来手动添加它,但这感觉不像“Rails 方式”。什么是?

解决方案 我最初的问题是在返回关联对象的错误假设下制定的debug()(这在 cakePHP 中有效,因为它将所有内容捆绑到数组中)。

所以我的原始代码应该可以工作。但是,我错误地命名了表中的外键。查看迁移方法t.belongs_to(它会自动创建正确命名的 foreign_key 字段,而不是名为“belongs_to”的字段),我感到困惑。因此,我还必须将该列重命名为user_id,现在它就像下面@V​​eraticus 的回答中描述的那样工作。

4

2 回答 2

39

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:您应该看到此时没有数据库调用。

于 2013-08-26T17:12:08.107 回答
6

急切加载,N+1 查询优化确实是在单个调用中加载关联的有效方式。

- 包含() 与 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, ....]}]
于 2014-01-09T08:14:55.527 回答