Ruby on Rails多表关联查询:如何实现指定SQL的ActiveRecord连接
搞定Rails多表关联查询的正确姿势
嘿,我看了你写的原生SQL和Model代码,现在帮你把关联调整对,然后就能用Rails优雅的写法实现这个查询啦!
首先得修正几个Model关联的小问题,毕竟Rails对关联的约定和外键匹配有要求:
1. 修正Model关联代码
User Model
这个基本没问题,Rails会自动用user_group_id作为外键,刚好和你的表结构匹配:
class User < ApplicationRecord self.table_name = "user" self.primary_key = "user_id" belongs_to :user_group end
UserGroup Model
这里有两个小错误:
has_many :user要改成复数has_many :users(Rails约定关联名必须是复数哦)- 和
user_group_info的关联搞反啦!从你的SQL能看出来,user_group_info表是靠user_group_id关联到user_group的,所以应该是has_many :user_group_infos(因为同一个分组可能对应不同语言的多条info,从language_id字段判断):
class UserGroup < ApplicationRecord self.table_name = "user_group" self.primary_key = "user_group_id" has_many :users # 修正为复数 has_many :user_group_infos, foreign_key: :user_group_id # 外键可以省略,只要表字段是user_group_id end
UserGroupInfo Model
同样,关联要改成belongs_to :user_group,因为它是从表,包含指向user_group的外键:
class UserGroupInfo < ApplicationRecord self.table_name = "user_group_info" belongs_to :user_group, foreign_key: :user_group_id end
2. 写出对应查询
关联调整好后,用Rails的joins方法就能实现嵌套内连接,完全对应你手写的SQL:
# 生成的SQL和你写的几乎一致 User.joins(user_group: :user_group_infos).where(user_group_infos: { language_id: 1 })
如果你的user_group和user_group_info是一对一关系(比如一个分组只有一条语言记录),那把UserGroup里的关联改成has_one :user_group_info,查询代码就改成:
User.joins(user_group: :user_group_info).where(user_group_info: { language_id: 1 })
要是你想验证生成的SQL对不对,直接加个.to_sql就行:
puts User.joins(user_group: :user_group_infos).where(user_group_infos: { language_id: 1 }).to_sql
这样就完美实现你要的多表查询啦!
内容的提问来源于stack exchange,提问作者Kase
相关产品推荐
相关产品推荐

