好的,让我们解释三种不同的方式来完成你正在寻找的东西。
首先, Includesincludes
和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
. 它只是以相同的顺序返回所选列的数组。就像在第一个示例中一样,您可以使用 pluck 获取配置文件对象的用户,@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
现在这将急切加载用户,但只会选择用户的电子邮件和 id。更多信息可以在
ActiveRecord 中找到。指定包含的列
更新
当您询问采摘的优点时,让我们解释一下。如您所知pluck
,返回的是普通数组。所以它不会实例化 ActiveRecord 对象,它只是返回从数据库返回的数据。所以 pluck 最好在不需要 ActiveRecord 对象的地方使用,而只是以表格形式显示返回的数据。Select 返回关系,以便您可以进一步查询它或在其实例上调用模型方法。因此,如果我们总结一下,我们可以说
pluck for model 值,select for model objects
更多信息可以在http://gavinmiller.io/2013/getting-to-know-pluck-and-select/找到