加入ActiveRecord has_one关系中的类型

时间:2013-08-13 10:05:51

标签: ruby activerecord sinatra

刚开始使用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配置文件或使用连接并接受每行的附加查询

以为我会检查我错过了一些明显的东西。

干杯

专利

1 个答案:

答案 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)