简体   繁体   English

如何在两个Ruby on Rails模型中连接列?

[英]How do I connect columns in two Ruby on Rails models?

I'm re-writing http://bngb.org as a Rails project (my first). 我正在将http://bngb.org重写为Rails项目(我的第一个)。 I've gone through Michael Hartl's tutorial. 我已经看过Michael Hartl的教程。 I've created Group and User models. 我已经创建了GroupUser模型。 A group belongs_to a user and a user has_one group, which is destroyed with the user. A组belongs_to一个用户和一个用户has_one基团,其被破坏与用户。

The contact email address for each group should be that of the user who owns the group, and should change when it changes. 每个组的联系电子邮件地址应该是拥有该组的用户的电子邮件地址,并且在更改时应更改。 I see that I can retrieve the address with group.user.email in my views, but it looks like this makes a database call each time instead of using cached data. 我看到我可以在视图中使用group.user.email检索地址,但是看起来这每次都使数据库调用而不是使用缓存的数据。 What's the correct way to have a group.email column which is linked to user.email ? 有一个链接到user.emailgroup.email列的正确方法是什么? Can I do it with what I have, or do I need a third table linked by has_one through: ? 我可以用自己拥有的做吗,还是需要通过has_one through:链接的第三张表?

Thanks very much for your help! 非常感谢您的帮助!
Jeff Covey 杰夫·科维

You can use ActiveRecord's after_find callback to add that to an attribute. 您可以使用ActiveRecord的after_find回调将其添加到属性中。 Here's an example: 这是一个例子:

class Group < ApplicationRecord
  belongs_to :user
  attr_accessor :email

  after_find :attach_email

  private

  def attach_email
    self.email = user.email
  end
end

It will make the initial database call to user when the object is retrieved from the database, and then save it as an attribute so all subsequent calls do not need to hit the DB. 当从数据库中检索对象时,它将对user进行初始数据库调用,然后将其另存为属性,因此所有后续调用都无需访问数据库。

You can use delegates . 您可以使用委托

class Group < ActiveRecord::Base
  belongs_to :user
  delegate :email, to: :user, allow_nil: true
end

It'll only make call to user table the first time you use group.email and will be cached for the subsequent calls. 它只会在您第一次使用group.email时对用户表进行调用,并将被缓存以供后续调用。

Anurag Aryan's answer suggesting delegate is a good start! Anurag Aryan的回答暗示delegate是一个好的开始! Given that Rails will cache results for your database queries, it might be good enough for you. 鉴于Rails将缓存数据库查询的结果,对您来说可能已经足够了。 Take a look at these docs to see what Rails does to avoid querying the DB . 查看这些文档, 了解Rails为避免查询数据库所做的工作 Have a close look at your server logs too and look for the word CACHE at the beginning of your queries. 也仔细查看您的服务器日志,并在查询开头查找CACHE一词。

Here is a sample (from one of my apps) of what to look for: 这是(从我的一个应用程序中)要查找的示例:

Unit Load (0.2ms)  SELECT  "units".* FROM "units" WHERE "units"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
↳ app/views/guests/reservations/_reservation.html.erb:5
CACHE Unit Load (0.0ms)  SELECT  "units".* FROM "units" WHERE "units"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
↳ app/views/guests/reservations/_reservation.html.erb:5

Notice the word CACHE on the third line? 注意第三行的CACHE吗? That's Rails reporting that the query didn't hit the DB. 这是Rails报告的查询未命中数据库。 If you want to avoid this additional query entirely use eager_load when getting the groups. 如果要避免此附加查询, eager_load在获取组时完全使用eager_load I think in your case, this will look like: 我认为您的情况如下所示:

@groups = Group.eager_load(:user).all

In your logs you should see that Rails will construct a query that joins your Groups and Users without a subsequent query. 在您的日志中,您应该看到Rails将构造一个查询,该查询将您的组和用户连接在一起,而无需后续查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM