Подтвердить что ты не робот

ActiveRecord Join Query и выберите в Rails

В моем приложении rails 4 клиент (таблица клиентов) может иметь много проектов (таблица проектов). У меня есть столбец с именем name в каждой таблице. Я пытаюсь написать join, а затем select, который использует проекты в качестве базовой таблицы и клиентов в качестве таблицы поиска. client_id - это 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 теряет одно из имен, как вы можете видеть из приведенного выше ответа. Как я должен писать этот запрос?

4b9b3361

Ответ 1

Если столбец в select не является одним из атрибутов модели, на которую вызывается select, то эти столбцы не отображаются. Все эти атрибуты все еще содержатся в объектах внутри AR::Relation и доступны как любые другие атрибуты публичного экземпляра.

Вы можете проверить это, вызвав first.client_name:

Project.joins(:client)
       .select('projects.id,projects.name,clients.name as client_name')
       .first.client_name

Ответ 2

Вы можете использовать :'clients.name' в качестве одного из ваших символов. Например:

Project.select(:id, :name, :'clients.name').joins(:client)

Мне это нравится больше, потому что кажется, что Rails это понимает, поскольку он цитирует все параметры:

SELECT "projects"."id","projects"."name","clients"."name"
FROM "projects"
INNER JOIN "clients" ON "clients"."id" = "projects"."client_id"

(я не уверен на 100%, что точный запрос SQL, но я вполне уверен, и я обещаю, что он будет использовать "clients"."name")

Ответ 3

ваш запрос не теряет ничего. На самом деле вы применили присоединение к моделям, и вы написали Project.joins(: client), почему он похож. означает, что он будет содержать связанные с Проектом данные, так как они связаны с данными с именем псевдонима, которые вы указали в своем запросе "client_name".

если вы используете

Project.joins(:client)
   .select('projects.id project_id, projects.name projects_name,clients.name as client_name')

тогда это выглядит     [#, #]

но он удерживает все атрибуты, которые вы выбрали.