概要
我正在将一个13年前的Rails 3应用程序升级到Rails 7应用程序,在Rails 5中使用where子句中的关联时遇到了一些问题。
逻辑
用户会有很多公司,但我们只想看看被设置为parent
的公司,或者我们标记为“我们目前关注”的公司。不仅如此,我们还希望只返回“我们当前关心的”母公司是master_company的用户。
用户通过UserCompanies拥有多家公司
UserCompanies有一个名为is_parent_company
的字段
公司有一个名为is_master_company
的字段
问题源代码
整个事情都围绕着一个关联:
has_many :parent_company, -> {where(user_companies: {is_parent_company: true})}, through: :user_companies, source: :company
它应该表示我们上面讨论过的parent_company
,它确实如此。
irb(main):067:0> User.first.parent_company
=> #<ActiveRecord::Associations::CollectionProxy [ #<some valid data> ] >
虽然在框架中使用这种关联和过滤器很有吸引力,但我对快速应用程序和可重用查询感兴趣,因此我需要一个可以构建的查询。这就把我们带到了问题所在:尝试在where子句中使用此关联,例如:
User.joins(:parent_company).where(parent_company: {is_master_company: true})
ActiveRecord正在查找一个名为parent_company
的表,并抛出了一个错误:missing FROM-clause entry for table "parent_company"
,这似乎是合理的:毕竟,我们是在连接它,并试图在where子句中使用它,就像我们在表中一样。
工作源代码
User.joins(user_companies: :company).where(user_companies: {is_parent_company: true, companies: {is_master_company: true}})
也许这就是Rails 3和4最初应该做的事情,原始代码只是解决方案代码。让我烦恼的是,这一直在“工作”,并为Rails 3和4吐出正确的用户,但我在Rails 5中抛出了这个错误。Rails 3和4是否支持在where子句中使用这种类型的关联?
这是相当令人困惑的,我提出这个问题是为了看看是否有人能为我指出从Rails 4到Rails 5的Active Record Query Interface更改的正确方向,这是引发此错误的原因。
感谢所有参与的人!
1条答案
按热度按时间n3schb8v1#
如果问题是“v4.x和v5.x之间发生了什么变化”,那么您必须深入研究代码库
https://github.com/rails/rails/blob/4-0-stable/activerecord/lib/active_record/relation/query_methods.rb
https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/relation/query_methods.rb
但是,您最终将不得不在底层方法中进行微小的更改,并且在完全了解ActiveRecord的核心内部之前,可能仍然得不到明确的答案。这种方法的好处是…您将完全了解ActiveRecord的核心内部结构。
不过,我想你已经触及到了更重要的问题:
我是否可以编写向后兼容的代码,这样我就有信心它会产生相同的结果?
也许这就是Rails 3和4最初应该做的事情,原始代码只是解决方案代码。
是的,看起来Rails < 4允许推断
:parent_company
的含义,但Rails 5+中的变化表明这是有问题的。您可以尝试@spickermann的建议,澄清您的关系以符合Rails约定。因为Rails是“约定优于配置”,所以关系中的多元化确实很重要。
在Rails 3、4和5中,仅这一点就有可能提供相同的行为。