3

サイドバーに、新しく作成したユーザー プロファイルを表示します。belongs_touser と user をプロファイルしますhas_one_profile。プロファイル テーブルの列は 3 つしか使用していないので、pluck を使用する方がよいことに気付きました。私もlink_to user_path(profile.user)部分的に a を持っているので、どういうわけかユーザーが誰であるかを伝える必要があります。現時点では を使用includesしていますが、ユーザー テーブル全体は必要ありません。そのため、ユーザー テーブルとプロファイル テーブルの両方から多くの列を使用しています。

これをpluckで最適化するにはどうすればよいですか? いくつかのバージョンを試しましたが、常に何らかのエラーが発生しました (ほとんどの場合、profile.user は定義されていません)。

私の現在のコード:

def set_sidebar_users
  @profiles_sidebar = Profile.order(created_at: :desc).includes(:user).limit(3) if user_signed_in?
end

create_table "profiles", force: :cascade do |t|
  t.integer  "user_id",      null: false
  t.string   "first_name",   null: false
  t.string   "last_name",    null: false
  t.string   "company",      null: false
  t.string   "job_title",    null: false
  t.string   "phone_number"
  t.text     "description"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "avatar"
  t.string   "location"
end
4

1 に答える 1

7

さて、探しているものを達成するための 3 つの異なる方法を説明しましょう。

まず、includesand joins includes に違いがあり、関連付け用に指定されたすべての列との関連付けを熱心にロードします。両方のテーブルから複数の列をクエリまたは選択することはできません。それは何joinsをしますか。両方のテーブルにクエリを実行し、選択した列を選択できます。

 def set_sidebar_users
  @profiles_sidebar = Profile.select("profiles.first_name,profiles.last_name,profiles.id,users.email as user_email,user_id").joins(:user).order("profile.created_at desc").limit(3) if user_signed_in?
end

句で指定Profilesしたすべての列を持つ関係が返されます。selectプロファイルオブジェクトと同じように取得できますe-g

@profiles_sidebar.first.user_emailは、このプロファイルのユーザー メールを提供します。

このアプローチは、複数のテーブルに対してクエリを実行する場合、または両方のテーブルから複数の列を選択する場合に最適です。

2.はじく

def set_sidebar_users
  @profiles_sidebar = Profile.order(created_at: :desc).includes(:user).limit(3).pluck("users.email,profiles.first_name") if user_signed_in?
end

Pluck は、複数の関連付けから列を取得するためにのみ使用されますが、 の機能を使用することはできませんActiveRecord。選択した列の配列を同じ順序で返すだけです。最初の例のように、プロファイル オブジェクトのユーザーを取得できますが@profiles_sidebar.first.user 、pluck では単純な配列であるため取得できません。そのため、ほとんどのソリューションでエラーが発生しますprofile.user is not defined

  1. 選択した列との関連付け。

これがオプション 3 です。最初のソリューションでは、両方のテーブルで複数の列を取得し、その機能を使用できますがActiveRecord、関連付けを積極的にロードしません。したがって、返された結果の関連付けを次のようにループすると、N + 1 クエリのコストがかかります @profiles_sidebar.map(&:user)

したがって、使用includesしたいが選択した列を使用したい場合は、選択した列との新しい関連付けを作成し、その関連付けを呼び出す必要があります。例えばprofile.rb

belongs_to :user_with_selected_column,select: "users.email,users.id"

これで、上記のコードに含めることができます

def set_sidebar_users
  @profiles_sidebar = Profile.order(created_at: :desc).includes(:user_with_selected_column).limit(3) if user_signed_in?
end

これでユーザーが熱心に読み込まれますが、ユーザーのメールと ID のみが選択されます。詳細については、 ActiveRecord のインクルードを参照してください。含まれる列を指定する

アップデート

プラックの長所について尋ねられたので、説明しましょう。ご存知pluckのように、プレーン配列が返されます。そのため、ActiveRecord オブジェクトをインスタンス化せず、データベースから返されたデータを返すだけです。したがって、pluck は、ActiveRecord オブジェクトを必要とせず、返されたデータを表形式で表示する場合に使用するのが最適です。Select はリレーションを返すので、さらにクエリを実行したり、そのインスタンスでモデル メソッドを呼び出したりできます。つまり、要約すると 、モデル値の場合はプル、モデル オブジェクトの場合は選択と言うことができます

詳細については、 http: //gavinmiller.io/2013/getting-to-know-pluck-and-select/を参照してください。

于 2016-03-21T11:27:30.883 に答える