rails4 采摘顺序和限制

rails4 pluck with order and limit

在我的侧边栏中,我显示了新创建的用户配置文件。配置文件 belongs_to 用户和用户 has_one_profile。我意识到我只使用了配置文件 table 中的 3 列,所以最好使用 pluck。我在部分中也有一个 link_to user_path(profile.user),所以我必须以某种方式告诉用户是谁。目前我正在使用 includes,但我不需要整个用户 table。所以我使用了来自用户和配置文件的许多列 tables.

如何使用 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

好的,让我们来解释三种不同的方法来完成您正在寻找的东西。

首先includesjoins是有区别的 仅包括预先加载与关联的所有指定列的关联。它不允许您从 table 查询或 select 多个列。它是 joins 所做的。它允许您查询您选择的 table 和 select 列。

 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

它会 return 你 Profiles 关系,其中包含你在 select 子句中提供的所有列。您可以像获取配置文件对象一样获取它们 e-g

@profiles_sidebar.first.user_email 将为您提供此配置文件的用户电子邮件。

如果您想查询多个 table 或想要 select 来自两个 table.

的多个列,这种方法是最好的

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

Pluck 仅用于从多个关联中获取列,但它不允许您使用 ActiveRecord 的强大功能。它只是 return 以相同的顺序为您提供 selected 列的数组。 就像在第一个示例中一样,您可以使用 @profiles_sidebar.first.user 获取配置文件对象的用户,但是使用 pluck 则不能,因为它只是一个普通数组。所以这就是为什么你的大多数解决方案都会引发错误 profile.user is not defined

  1. 与 select 编辑的列关联。

现在这是选项三。在第一个解决方案中,您可以在两个 table 上获得多个列并使用 ActiveRecord 的功能,但它不会急于加载关联。因此,如果您在 returned 结果上循环关联 @profiles_sidebar.map(&:user)

,它仍然会花费您 N+1 个查询

因此,如果您想使用 includes 但想使用 selected 列,那么您应该与 selected 列建立新的关联并调用该关联。 例如 在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

现在这将急切加载用户,但 select 只会加载用户的电子邮件和 ID。 更多信息可以在 ActiveRecord includes. Specify included columns

更新

正如您询问的关于 pluck 的优点,让我们来解释一下。 如您所知,pluck return 是普通数组。因此它不会实例化 ActiveRecord 对象,它只是 return 向您提供从数据库中 return 编辑的数据。 所以 pluck 最好用在不需要 ActiveRecord 对象而只是以表格形式显示 returned 数据的地方。 Select return 为您提供关系,以便您可以进一步查询它或在它的实例上调用模型方法。 所以如果我们总结一下,我们可以说 pluck 用于模型值,select 用于模型对象

可以在 http://gavinmiller.io/2013/getting-to-know-pluck-and-select/

找到更多信息