Rails 4中joins+where无法生成正确SQL,仅squeel Gem可正常生成
解决命名空间模型关联查询的SQL生成问题
嘿,我懂你碰到的这个问题了——用了命名空间下的Notification::User和Notification::Address做关联查询时,默认的Active Record写法生成的SQL不对,只有借助Squeel才能得到预期的正确语句?不用慌,咱们不用依赖第三方gem也能搞定,给你几个可行的方案:
方案1:给关联显式指定表名
Rails处理命名空间模型时,偶尔会在推断关联表名时出错,咱们直接在关联定义里把表名写死就好:
class Notification::User < ApplicationRecord has_many :addresses, class_name: "Notification::Address", dependent: :nullify, table_name: "notification_users" end class Notification::Address < ApplicationRecord belongs_to :user, class_name: "Notification::User", table_name: "notification_users" end
这么一来,Active Record就能准确识别关联的表,执行查询时自然会生成正确的JOIN和WHERE条件。
方案2:查询时明确指定模型/表名
如果不想改动关联定义,也可以在写查询语句的时候主动消除歧义:
方式A:用Arel表对象(最推荐,可读性强)
Notification::Address.joins(:user) .where(Notification::User.arel_table[:name].eq('Test')) .to_sql
方式B:直接写原生SQL片段
Notification::Address.joins(:user) .where('notification_users.name = ?', 'Test') .to_sql
方式C:哈希语法里用完整模型类作为键
Notification::Address.joins(:user) .where(Notification::User => { name: 'Test' }) .to_sql
方案3:确保模型表名设置正确
虽然Rails默认会根据命名空间生成表名(比如Notification::User对应notification_users),但有时候可能因为自定义配置出问题,咱们可以在模型里显式声明表名:
class Notification::User < ApplicationRecord self.table_name = "notification_users" has_many :addresses, dependent: :nullify end class Notification::Address < ApplicationRecord self.table_name = "notification_addresses" belongs_to :user end
这样能彻底避免Rails搞错表名,关联查询的SQL自然就正确了。
以上几种方法都能帮你摆脱对Squeel的依赖,生成你想要的SQL语句,选个适合你代码结构的就行~
内容的提问来源于stack exchange,提问作者ant
相关产品推荐
相关产品推荐

