.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'
_
関連するユーザーハッシュ/配列をこれに含めるべきではありませんか? 2番目のfind
/where
(_@project.user = User.where( {:id=>@project.belongs_to}
_)を呼び出して手動で追加できることは知っていますが、これは「The Rails方法」とは何ですか?
Solution私の最初の質問は、debug()
が関連オブジェクトを返すという誤った仮定の下で定式化されました(これは、すべてを配列にバンドルするため、cakePHPで機能します)。
だから私の元のコードshouldは動作します。ただし、テーブルにファイルされた外部キーの名前は間違っていました。移行方法_t.belongs_to
_(正しい名前のforeign_keyフィールドを自動的に作成し、not「belongs_to」というフィールドを見て混乱しました) 。そのため、その列の名前を_user_id
_に変更する必要もありましたが、現在は以下の@Veraticusの回答で説明されているとおりに機能します。
user
オブジェクトはproject
オブジェクトの一部ではないため、プロジェクトで表示することはできません。むしろ、Project.includes(:user)
と言うことで、 telling 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クエリの最適化は、1回の呼び出しで関連付けを読み込む効率的な方法です。
-where()およびfind()を含むinclude()
@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, ....]}]