0

刚刚开始使用 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

给我正确的数据,并为第一个查询使用内部联接,但随后发出第二个查询以获取配置文件数据

它还给出了一个折旧的警告并建议我使用负载,我尝试过但不会使用内部连接。

类似的情况

user = User.joins(:profile).first
user.profile.user_age

我得到一个内部连接,但每个用户行都有一个查询。

我试过包括

user = User.includes(:profile).first
user.profile.user_age

这种延迟加载配置文件并会减少循环中的查询数量,但是我认为它也会拉动没有配置文件的用户

我也试过参考

user = User.includes(:profile).references(:profile).first
user.profile.user_age

这为我提供了正确的数据并将查询减少到 1,但使用了LEFT JOIN

我可能还没有完全掌握它并且正在尝试实现一些不可行的事情,我想我可能需要使用包含并检查循环内的 nil 配置文件,或者使用连接并接受每一行的附加查询。

以为我会检查以防我遗漏了一些明显的东西。

干杯

拍。

4

1 回答 1

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)
于 2013-08-13T11:35:22.997 回答