我有以下关联:
mobile_application.rb
has_many :events
event.rb
belongs_to :mobile_application
以下内容可以正常运行:
MobileApplication.includes(:events)
#=> MobileApplication Load (1.6ms) SELECT `mobile_applications`.* FROM `mobile_applications` ORDER BY created_at desc
# Event Load (1.3ms) SELECT `events`.* FROM `events` WHERE `events`.`mobile_application_id` IN (746, 745, 744, ....
但是当我尝试以下操作时,
MobileApplication.includes(:events).where("events.expiry_date >= ?", Time.zone.now)
它引发错误:
MobileApplication Load (1.2ms) SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517') ORDER BY created_at desc
Mysql2::Error: Unknown column 'events.expiry_date' in 'where clause': SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517') ORDER BY created_at desc
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'events.expiry_date' in 'where clause': SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517') ORDER BY created_at desc
更新
请提出如何进行过滤的建议。使用references
还会引发以下错误,并且与Marek Lipka提供的答案相同,
ActiveRecord::StatementInvalid: Mysql2::Error: Column 'created_at' in
order clause is ambiguous: SELECT `mobile_applications`.`id` AS t0_r0,
`mobile_applications`.`name` AS t0_r1, ...
我想这是由于模型中存在的default_scope
创建的列歧义性导致两个关联表中都存在的created_at
对其进行了排序。
答案 0 :(得分:2)
默认情况下,/usr/local/bin/
不执行includes
,而是执行两个单独的数据库查询。您可以使用left join
强制left join
,如下所示:
eager_load
或者,如果您实际上不需要急切加载(我不知道),则可以简单地使用MobileApplication.eager_load(:events).where('events.expiry_date >= ?', Time.zone.now)
:
joins
关于使用MobileApplication.joins(:events).where('events.expiry_date >= ?', Time.zone.now)
或references
时的错误:您显然尝试通过eager_load
在某个地方(尽管您未在问题中包括此点)进行订购,例如:
created_at
因此,显然,DB不知道您打算使用order('created_at DESC')
使用哪个表,因为joins
或created_at
中都有mobile_applications
列。因此,您需要指定“目标”表,例如:
events
答案 1 :(得分:0)
在rails 4.x中,您必须添加关键字references
:
MobileApplication.includes(:events).references(:events).where("events.expiry_date >= ?", Time.zone.now)