Rails中如何在Where语句计算里使用关联表的字段?
解决Rails关联表字段在WHERE条件中参与计算的问题
你的核心问题是要让数据库层面使用关联表developers的auto_complete字段做日期计算,而非在Ruby层面调用单个对象的方法。下面提供两种可行方案:
方案一:直接使用原生SQL字符串
根据你使用的数据库类型选择对应写法:
MySQL/MariaDB
Plot.joins(:developer) .where('plots.reservation_release_date < DATE_SUB(NOW(), INTERVAL developers.auto_complete MONTH)')
PostgreSQL
Plot.joins(:developer) .where('plots.reservation_release_date < CURRENT_DATE - (developers.auto_complete || \' months\')::interval') # 或者更简洁的写法 Plot.joins(:developer) .where('plots.reservation_release_date < CURRENT_DATE - INTERVAL \'1 month\' * developers.auto_complete')
方案二:使用Arel(无需深入掌握,直接复用示例代码)
先获取表的Arel对象,再构建条件:
plot = Plot.arel_table developer = Developer.arel_table # MySQL版本 Plot.joins(:developer) .where(plot[:reservation_release_date].lt( Arel::Nodes::NamedFunction.new('DATE_SUB', [Arel.sql('NOW()'), Arel::Nodes::SqlLiteral.new("INTERVAL #{developer[:auto_complete].to_sql} MONTH")]) )) # PostgreSQL版本 Plot.joins(:developer) .where(plot[:reservation_release_date].lt(Arel.sql("CURRENT_DATE - INTERVAL '1 month' * #{developer[:auto_complete].to_sql}")))
原代码失效原因
原代码中developer.auto_complete.months.ago是在Ruby环境执行的,这里的developer是单个实例对象,无法对应查询中每条Plot关联的Developer记录的auto_complete值,必须把计算逻辑放到SQL语句里,让数据库对每条记录的关联字段值进行计算。
内容的提问来源于stack exchange,提问作者user1587804
相关产品推荐
相关产品推荐

