has_many/belongs_to 关系和查询问题

has_many/belongs_to relationships & query questions

我现在正在构建一个考勤跟踪器。我目前有三个模型。我正在为我的用户模型使用设计

class User < ActiveRecord::Base
  has_many :clients
  has_many :attendances

class Client < ActiveRecord::Base
  belongs_to :user
  has_many :attendances

class Attendance < ActiveRecord::Base
  belongs_to :user
  belongs_to :client

出勤率table的栏是user_idclient_idcreated_atupdated_at

这是我的思考过程:
我可以获得每个 User
的所有出席人数 我还可以获得特定 Client
的所有出席人数 我可以通过以下方式获取特定 UserClient 的所有出勤记录:Attendance.joins(:user, :client).where(:user_id => current_user) 其中 returns 和

<ActiveRecord::Relation [#<Attendance id: 18, client_id: 151, created_at: "2015-07-24 21:36:16", updated_at: "2015-07-24 21:36:16", user_id: 4>, #<Attendance id: 19, client_id: 101, created_at: "2015-07-24 21:37:10", updated_at: "2015-07-24 21:37:10", user_id: 4>, #<Attendance id: 20, client_id: 114, created_at: "2015-07-24 21:37:39", updated_at: "2015-07-24 21:37:39", user_id: 4>, #<Attendance id: 21, client_id: 123, created_at: "2015-07-24 21:38:26", updated_at: "2015-07-24 21:38:26", user_id: 4>]>

我能否以某种方式参考 Client table 以获取 first_nameemail 等信息以及另一个 whereinclude、或 joins 声明?

或者我是否完全遗漏了一些东西,可能需要加入 table 并建立 has_many, through: 关系?

Brad 的上述评论在技术上是正确的,但由于您查询中的 .joins 子句仅包含用于执行实际查询的那些 table,来自用户和客户的数据 tables 实际上不会被 Rails 加载,所以为了获取它们的所有数据,你最终将执行 N+1 次查询(Rails 应用程序缓慢的常见原因!)。即:

irb> User.joins(:groups).each { |u| u.groups.map(&:name) }
  User Load (8.6ms)  SELECT "users".* FROM "users" INNER JOIN "groups" ON "groups"."user_id" = "users"."id"
  Group Load (1.2ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" =   [["user_id", 1]]
  Group Load (0.6ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" =   [["user_id", 1]]
  Group Load (0.7ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" =   [["user_id", 1]]
  Group Load (0.7ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" =   [["user_id", 2]]
  Group Load (0.6ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" =   [["user_id", 3]]

现在还不错,但想象一下如果您有 1000 个用户!不过,我们可以解决这个问题。如果您使用 .includes 方法,您将同时加入其他 table(s) 并将它们的数据加载到内存中。它仍然运行 2 个查询,但这是一个改进:

irb(main):016:0> User.includes(:groups).each { |u| u.groups.map(&:name) }
  User Load (0.6ms)  SELECT "users".* FROM "users"
  Group Load (1.2ms)  SELECT "groups".* FROM "groups" WHERE "groups"."user_id" IN (1, 2, 3, 4)

所以,对于你的情况,试试这个:

Attendance.includes(:user, :client).where(user_id: current_user)

有关 includesjoins 之间区别的更多信息,请参阅 this blog post 或 Google "rails joins vs includes"。