Хорошо давайте объясним три различных способа сделать то, что вы ищете.
Прежде всего, существует разница в includes
и joins
Включает в себя только загруженную нагрузку ассоциацию со всеми указанными столбцами для ассоциаций. Это не позволяет вам запрашивать или выбирать несколько столбцов из обеих таблиц. Это то, что делают 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.Pluck
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
Ливер просто используется, чтобы получить столбцы из нескольких ассоциаций, но это не позволяет использовать возможности ActiveRecord
. Он просто возвращает вам массив выбранных столбцов в том же порядке. Как и в первом примере, вы можете получить пользователя для объекта профиля с @profiles_sidebar.first.user
Но с вырывом вы не можете, потому что это просто простой массив. Вот почему большинство ваших решений вызывает ошибку profile.user is not defined
- Ассоциация с выбранными столбцами.
Теперь это вариант три. В первом решении вы можете получить несколько столбцов на обеих таблицах и использовать мощность 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
Теперь это нетерпеливые пользователи нагрузки, но будет выбрать только адрес электронной почты и идентификатор пользователя. Более подробную информацию можно найти на ActiveRecord includes. Specify included columns
UPDATE
Как вы спросили о преимуществах для срывать так давайте объяснить. Как вы знаете, pluck
возвращает вам простой массив. Таким образом, он не создает экземпляр объекта ActiveRecord, он просто возвращает вам данные, возвращенные из базы данных. Так что pluck лучше всего использовать, где вам не нужны объекты ActiveRecord, а просто для отображения возвращенных данных в табличной форме. Select возвращает вам отношения, чтобы вы могли запросить его или вызвать методы модели в своих экземплярах. Так что, если мы Итоги его можно сказать срывать для модельных значений, выберите для модели объектов
Дополнительная информация может быть найдена на http://gavinmiller.io/2013/getting-to-know-pluck-and-select/
Вы пробовали что-то вроде 'Profile.order (created_at:: по убыванию) .limit (3) .pluck (: 'users.name') '? Другим возможным ответом может быть сделать ваш первый запрос (без включений), а затем сделать '@ profiles_sidebar.users.pluck (: username)'. Я также нашел два потока, которые могли бы помочь вам в этом вопросе: [this] (http://stackoverflow.com/a/18131149/2929693) и [this] (http://stackoverflow.com/a/26538974/2929693) , –
Я думаю, вам не нужно использовать здесь. Если вы хотите с нетерпением загружать ассоциацию + загружать выбранные столбцы, тогда есть способ сделать это. Во-вторых, если вам нужны только выбранные clumns из обеих таблиц, просто используйте объединения, а не include. lemme написать ответ –