eme*_*his 22 ruby ruby-on-rails associations ruby-on-rails-4
我无法弄清楚如何使用该.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
Run Code Online (Sandbox Code Playgroud)
在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'
Run Code Online (Sandbox Code Playgroud)
不应该将相关的用户哈希/数组包含在此中吗?我知道我可以通过调用第二个find/ where(@project.user = User.where( {:id=>@project.belongs_to})手动添加它,但这不像"Rails方式".什么是?
解决方案
我的初始问题是在不正确的假设下制定的,debug()它将返回相关的对象(这在cakePHP中起作用,因为它将所有内容捆绑到数组中).
所以我的原始代码应该可行.但是,我错误地将表中的外键命名为.通过查看迁移方法t.belongs_to(自动创建正确命名的foreign_key字段,而不是名为"belongs_to"的字段),我感到困惑.所以我还必须重命名该列user_id,现在它的工作方式与下面的@Veraticus的答案中描述的一样.
Ver*_*cus 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
Run Code Online (Sandbox Code Playgroud)
并热切地:
@project = Project.includes(:user).where(id: params[:id]).first # one database call, fetching both project and user
@project.user # no database interaction
Run Code Online (Sandbox Code Playgroud)
这has_many对于预先加载关联可以保存N + 1个数据库查询的查询更为重要.
您可以通过@project.user在预先加载并检查日志之后的某个时刻调用来验证这是否正常工作:您应该看到此时没有数据库调用.
热切加载,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
Run Code Online (Sandbox Code Playgroud)
*在某些情况下,它可能是有用的*
@projects = Project.find(:all, :includes => :user)
@projects = Project.find(:all, :include => [{:association1 => [:associationA, :associationB, ....]}]
Run Code Online (Sandbox Code Playgroud)