0

私のアプリでは、主なオブジェクトはアカウントと電話であり、典型的なhas_many:throughContactsを使用します。

Account:
has_many :contacts
has_many :phones, :though => contacts

Phone:
has_many :contacts
has_many :accounts, :though => :contacts

Contact:
belongs_to :account
belongs_to :phone

連絡先にはsignup_status、nameのフィールドがあります一意のアカウント/電話のペアごとに1つの連絡先があります

id = 123のアカウントで、5つの連絡先があり、各連絡先に1つの電話がある場合、5つの行すべてを生成し、すべてのアカウントフィールドと連絡先フィールドと電話フィールドを含むクエリはありますか?

4

2 に答える 2

2

アソシエーションの積極的な読み込みを使用して、1つのアクティブなレコードクエリで必要なすべてのデータを取得できます

@account = Account.includes(:contacts, :phones).find(123)

、これは実際には3つのSQLクエリに変換されます。

SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1  [["id", 123]]
SELECT "contacts".* FROM "contacts" WHERE "contacts"."account_id" IN (123)
SELECT "phones".* FROM "phones" WHERE "phones"."id" IN (<phone ids found in prev query>)

すべてのレコードがメモリにロードされ、@accountを介して利用できるようになります。@account.contacts連絡先と電話の配列を取得するには、それぞれとに電話するだけ@account.phonesです。これらの呼び出しでは、SQLクエリが再発行されないことに注意してください。これは、積極的な読み込みの利点です。

于 2012-09-26T05:15:48.247 に答える
1

ActiveRecordは、1つのSQLクエリですべてを実行できるほど賢くはありません。ただし、includesを使用すると、n+1個のクエリを回避できます。

Account.includes(:contacts => :phones).where(:id => 123)

ActiveRecordは、1つのクエリを実行してすべてのアカウントレコードをロードし、1つのクエリを実行してすべての連絡先をロードし、1つのクエリを実行してすべての電話をロードします。この背後にある理由については、以下のドキュメントへのリンクを参照してください。

本当にすべてを1つのSQLクエリで取得したい場合(これには欠点があります)、 ActiveRecord :: Associations :: Preloader(ドキュメント)を確認する必要があります。

于 2012-09-26T05:12:04.360 に答える