私のRails 4アプリケーションでは、クライアント(clientsテーブル)は多くのプロジェクト(projectsテーブル)を持つことができます。各テーブルにname
という列があります。 join
に続いてselect
は、プロジェクトをベーステーブルとして使用し、クライアントをルックアップテーブルとして使用しますclient_id
はprojectsテーブルのforeign_key
です:
私は次のようにクエリを書いています:
Project.joins(:client).select('projects.id,projects.name,clients.name')
私は次の応答を受け取ります:
Project Load (0.6ms) SELECT projects.id,projects.name,clients.name FROM "projects" INNER JOIN "clients" ON "clients"."id" = "projects"."client_id"
=> #<ActiveRecord::Relation [#<Project id: 1, name: "Fantastico Client">]>
次のようにエイリアスしようとすると:
Project.joins(:client).select('projects.id,projects.name,clients.name as client_name')
その後、次の応答が返されます。
Project Load (0.8ms) SELECT projects.id,projects.name,clients.name as client_name FROM "projects" INNER JOIN "clients" ON "clients"."id" = "projects"."client_id"
=> #<ActiveRecord::Relation [#<Project id: 1, name: "The Dream Project">]>
どちらの場合でも、上記の応答からわかるように、ActiveRecordは名前の1つを失います。このクエリをどのように書くべきですか?
select
の列が、select
が呼び出されるモデルの属性のいずれでもない場合、それらの列は表示されません。これらの属性はすべてAR::Relation
内のオブジェクトに含まれており、他のパブリックインスタンス属性としてアクセスできます。
これを確認するには、first.client_name
を呼び出します。
Project.joins(:client)
.select('projects.id,projects.name,clients.name as client_name')
.first.client_name
_:'clients.name'
_をシンボルの1つとして使用できます。例えば:
Project.select(:id, :name, :'clients.name').joins(:client)
Railsはすべてのパラメーターを引用するため、Rails $ ===はそれを理解しているように見えるので、私はそれがより好きです:
_SELECT "projects"."id","projects"."name","clients"."name" as "client_name" FROM "projects" INNER JOIN "clients" ON "clients"."id" = "projects"."client_id"
_
(私はそれが正確なSQLクエリであることを100%確信しているわけではありませんが、私はかなり確信しており、それを約束しますwill use _"clients"."name"
_)
クエリで何かが失われることはありません。実際に、モデルに結合を適用し、Project.joins(:client)を記述して、その理由を説明します。は、プロジェクト関連のデータをそのまま保持し、クエリで「client_name」を指定したエイリアス名に関連付けられたデータを保持することを意味します。
使用する場合
Project.joins(:client)
.select('projects.id project_id, projects.name projects_name,clients.name as client_name')
[#、#]のようになります
ただし、選択したすべての属性が保持されます。