0

(sinatra アプリで) ActiveRecord を使い始めたところです。既存のクエリを AR に移植しようとしていますが、少し行き詰っています。

ユーザーとプロファイルにhas_oneリレーションがある場合(残念ながら従来のテーブルを使用)

class User < ActiveRecord::Base

    self.table_name = "systemUsers"
    self.primary_key = "user_id"

    has_one :profile, class_name: 'Profile', foreign_key: 'profile_user_id'
end

class Profile < ActiveRecord::Base

    self.table_name = "systemUserProfiles"
    self.primary_key = "profile_id"

    belongs_to :user, class_name: "User", foreign_key: 'user_id'
 end

内部結合を使用してプロファイルを持つすべてのユーザーにクエリを実行する場合、1 つのクエリを使用してプロファイルから user_age フィールドを取得できますか?

たとえば (コードを減らすために .first を追加しましたが、プロファイルを持つすべてのユーザーをループします)

user = User.all(:joins => :profile).first
user.profile.user_age

正しいデータが得られ、最初のクエリに INNER 結合を使用しますが、2 番目のクエリを発行してプロファイル データを取得します

また、減価償却の警告が表示され、負荷を使用するように提案されますが、試してみましたが、内部結合は使用しません。

との類似事例

user = User.joins(:profile).first
user.profile.user_age

INNER 結合を取得しますが、ユーザー行ごとにクエリを取得します。

私は含めてみました

user = User.includes(:profile).first
user.profile.user_age

これはプロファイルを遅延ロードし、ループ内のクエリの数を減らしますが、プロファイルのないユーザーもプルすると思います

私も参考にしてみました

user = User.includes(:profile).references(:profile).first
user.profile.user_age

これにより、正しいデータが得られ、クエリが 1 に減りますが、LEFT JOINが使用されます

私はおそらくそれを完全に把握しておらず、実行できないことを達成しようとしています.ループ内でインクルードを使用してnilプロファイルをチェックするか、結合を使用して各行の追加のクエリを受け入れる必要があると考えました.

明らかな何かが欠けている場合に備えてチェックすると思いました。

乾杯

パット。

4

1 に答える 1

1

プロファイルには常に 1 人のユーザーが必要です。したがって、私はProfile.first.user_age最初のユーザー プロファイルに対して行います。しかし、あなたのようにユーザーアプローチで行くと、

User.find { |u| u.profile }.profile.user_age

User.find { |u| u.profile }値を持つ最初のユーザーを返しtrueます。

すべてのユーザー プロファイルを照会し、user_ages を取得します。すべてのプロファイルに user_id があり、そうであると仮定します。

 Profile.pluck(:user_age)

ユーザー ID なしでプロファイルを保存する場合、これは user_id の存在をチェックします。これwhere.notは Activerecord の新機能です。バージョンを確認してください。

 Profile.where.not(user_id: nil).pluck(:user_age)
于 2013-08-13T11:35:22.997 に答える