我正在建立一个考勤跟踪器。我目前有三种型号。我正在为我的用户模型使用设计
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
考勤表上的列为user_id
client_id
created_at
和updated_at
这是我的思考过程:
我可以获得每个User
的所有参加人数
我还可以获得特定Client
的所有出席情况
我可以通过以下方式获取特定User
和Client
的所有出勤记录:Attendance.joins(:user, :client).where(:user_id => current_user)
返回
<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
表,以获取first_name
或email
与其他where
,include
或joins
等信息声明?
或者我完全错过了某些内容,可能需要一个联接表并建立has_many, through:
关系?
答案 0 :(得分:0)
Brad上面的评论在技术上是正确的,但由于查询中的.joins
子句仅包含用于执行实际查询的那些表,因此来自Users和Clients表的数据实际上不会被加载在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" = $1 [["user_id", 1]]
Group Load (0.6ms) SELECT "groups".* FROM "groups" WHERE "groups"."user_id" = $1 [["user_id", 1]]
Group Load (0.7ms) SELECT "groups".* FROM "groups" WHERE "groups"."user_id" = $1 [["user_id", 1]]
Group Load (0.7ms) SELECT "groups".* FROM "groups" WHERE "groups"."user_id" = $1 [["user_id", 2]]
Group Load (0.6ms) SELECT "groups".* FROM "groups" WHERE "groups"."user_id" = $1 [["user_id", 3]]
现在还不错,但想象一下,如果你有一千个用户!不过,我们可以解决这个问题。如果使用.includes
方法,则您将加入其他表并将其数据加载到内存中。它仍然运行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)
有关includes
和joins
之间差异的详细信息,请参阅this blog post或Google“rails joins vs includes”。