刚开始使用ActiveRecord(在sinatra应用程序中)。尝试将现有查询移植到AR,但稍微陷入困境。
如果我对用户和个人资料有 has_one 关系(遗憾的是使用旧表)
class User < ActiveRecord::Base
self.table_name = "systemUsers"
self.primary_key = "user_id"
has_one :profile, class_name: 'Profile', foreign_key: 'profile_user_id'
end
class Profile < ActiveRecord::Base
self.table_name = "systemUserProfiles"
self.primary_key = "profile_id"
belongs_to :user, class_name: "User", foreign_key: 'user_id'
end
如果我想使用内部联接查询所有具有配置文件的用户,那么可以使用一个查询从配置文件中获取user_age字段吗?
例如,(刚刚添加.first以减少代码,但会循环遍历所有使用个人资料的用户)
user = User.all(:joins => :profile).first
user.profile.user_age
为我提供正确的数据,并为第一个查询使用INNER联接,但随后发出第二个查询以获取个人资料数据
它还给出了折旧警告,并建议我使用load,我试过但不会使用内连接。
与
类似的情况user = User.joins(:profile).first
user.profile.user_age
我得到一个INNER连接,但是每个用户行都有一个查询。
我试过包含
user = User.includes(:profile).first
user.profile.user_age
这个延迟加载配置文件并会减少循环中的查询数量,但是我认为它会拉动没有配置文件的用户
我也尝试过参考
user = User.includes(:profile).references(:profile).first
user.profile.user_age
这为我提供了正确的数据并将查询减少为1但使用了 LEFT JOIN
我可能还没有完全理解它并且正在尝试实现一些不可行的东西,我想我可能需要使用包含并检查循环内的nil配置文件或使用连接并接受每行的附加查询
以为我会检查我错过了一些明显的东西。
干杯
专利
答案 0 :(得分:1)
个人资料应该始终有一个用户。所以,我会为第一个用户个人资料Profile.first.user_age
。但是像你一样遵循用户方法,
User.find { |u| u.profile }.profile.user_age
User.find { |u| u.profile }
返回值为true
的第一个用户。
查询所有用户个人资料并获取他们的user_ages。假设所有配置文件都有user_id,那应该是这种情况。
Profile.pluck(:user_age)
如果您保存没有用户ID的配置文件,则会检查user_id是否存在。此where.not
是Activerecord中的新功能,请检查您的版本。
Profile.where.not(user_id: nil).pluck(:user_age)