【问题标题】:Referencing an associated table in an ActiveRecord where/join call在 ActiveRecord where/join 调用中引用关联表
【发布时间】:2012-01-19 22:15:22
【问题描述】:

假设我有两个 Rails 模型,用户和列表。用户有_许多列表和列表属于_一个用户。

用户在任何给定时间都有一个他们正在处理的特定列表。这由 User 模型上的 active_list_id 外键表示。

假设我想通过 ActiveRecord 运行以下查询的等效项:

SELECT * FROM users JOIN lists 
ON lists.id = users.active_list_id

基本上,我正在尝试编写一种方法,该方法将让每个用户连同她当前的活动列表一起显示列表完成的统计信息。

在我看来,解决方案类似于

Users.joins(:lists).where("users.active_list_id  = lists.id") 

但我似乎无法让它工作**,而且我不确定 Rails 中最惯用的正确解决方案是什么。

我应该如何使用 ActiveRecord 最有效地提取这些数据?

提前感谢您提供的任何帮助。

编辑:上面的查询确实有效,但似乎没有提取用户记录及其关联列表的连接。

【问题讨论】:

  • 通常表名是“users”和“lists”——这可能是你的问题吗?
  • 好电话,但不,那是我的错误。这些表格实际上是小写的。为了清楚起见,我将编辑我的问题,谢谢。
  • 我误解了,问题是查询而不是表。你是对的,没有大写的查询返回我需要的用户,但它似乎也不包括列表记录。
  • 该死。好吧,你在做什么看起来是正确的。您是否在 mysql 控制台中尝试过该 SQL?您是否尝试过制作一个更简单的 where 子句(例如,'lists.id = 1' 或其他一些琐碎的东西)来尝试隔离它发生故障的位置?
  • 我确实在 sql 控制台中尝试过(实际上是 sqlite)...SQL 中的查询返回连接的两个表记录...*headscratch*

标签: ruby-on-rails activerecord join


【解决方案1】:

您的帖子中有一些奇怪的东西。第一件事是:“have_many”错了,它叫做has_many,如果它在你的模型中就像你写下来的那样可能是个问题!然后另一件事就是外键的名称!按照惯例,外键是单数形式的关联名称加上 _id。当你说你想拥有user.lists时,外键必须叫list_id而不是active_list_id!您可以通过在关联中传递foreign_key 选项来指定非传统外键!看起来像这样:

用户.rb:

has_many :lists, :foreign_key => 'active_list_id'

列表.rb:

belongs_to :user, :foreign_key => 'active_list_id'

那么你就可以这样说:

User.find(<id>).lists

您永远不会使用 SQL 连接 Rails 中的表!不要试图将 PHP 知识转移到 RoR 1 对 1,只是不要!

// 啊,现在我明白你需要的是一个带参数的范围! 用户.rb:

scope :active_list, lambda{|list_id| where(:active_list_id =>  list_id)}

然后您可以拨打User.active_list(&lt;list_id&gt;) 获取所有使用此列表的用户!

【讨论】:

  • 确实,has_many 是一时的失误,在我的模型中实际上并不是这样......并且认为我读了五次这个问题>_<...... active_list_id user_id>
  • 干杯,这很棒,我认为使用范围将使代码保持干燥,并且考虑到我可能会经常使用该范围,这非常适合项目。非常感谢 =)
  • 请注意,使用 lambda 会导致性能问题。在 RDMBS 的某些用途中,lambda 可以将所有数据加载到内存中,然后循环遍历它以获取条件。
  • lambda 问题有时被称为N+1 问题和is identified in the Rails Docs
  • 永远不要说永远,除了说“永远不要说永远”
【解决方案2】:

试试这个:

Users.includes(:lists).where("users.active_list_id  = lists.id") 

您在问题中所做的是加载符合该条件的用户,而您想要的也是 eager-load the association

虽然真的,您可能需要考虑将其设为单独的关联:

class User
  belongs_to :active_list, :class_name => :list
end

class List
  has_one :user
end

【讨论】:

  • 它的工作原理是它允许我将结果插入到一个变量中,然后通过它们查找每个变量的完成统计数据并相应地对它们进行排名。我想知道以这种方式执行此操作还是进行一个查询以将必要字段添加到结果中是否更好(即,将 lists.pct_completed 添加到每个用户记录)...无论如何,谢谢您的帮助.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-23
  • 2014-06-27
  • 2019-08-18
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
相关资源
最近更新 更多