Rails查询,基于不相关模型中的范围

格沃尔辛顿

我想找到一个用户的所有的convos那里是不是connect

我有一个convos表,带有sender_idrecipient_id,这两个都是对用户ID的引用

# app/models/user.rb

has_many :convos, ->(user) {
  unscope(:where).where("sender_id = :id OR recipient_id = :id", id: user.id)
}

请注意,convo可以属于sender_id或receive_id的用户。

# app/models/convo.rb

class Convo < ApplicationRecord
  belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
  belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'

  has_many :msgs, dependent: :destroy

  validates_uniqueness_of :sender_id, :scope => :recipient_id

  scope :involving, -> (user) do
    where("convos.sender_id =? OR convos.recipient_id =?",user.id,user.id)
  end

  scope :between, -> (sender_id,recipient_id) do
    where("(convos.sender_id = ? AND convos.recipient_id =?) OR (convos.sender_id = ? AND convos.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id)
  end
end

Connect表中有requestor_idrequestee_id都是对用户ID的引用。连接模型

class Connect < ApplicationRecord
  belongs_to :requestor, :foreign_key => :requestor_id, class_name: 'User'
  belongs_to :requestee, :foreign_key => :requestee_id, class_name: 'User'


  scope :between, -> (requestor_id,requestee_id) do
    where("(connects.requestor_id = ? AND connects.requestee_id =?) OR (connects.requestor_id = ? AND connects.requestee_id =?)", requestor_id,requestee_id, requestee_id, requestor_id)
  end
end

我想找到一个用户的所有的convos那里是不是connect

我已经尝试过类似的方法:

user = User.first
user.convos.where.not(Connect.between(self.requestor_id, self.requestee_id).length > 0 )

# NoMethodError (undefined method `requestor_id' for main:Object)

user.convos.where.not(Connect.between(convo.requestor_id, convo.requestee_id).length > 0 )

# undefined local variable or method `convo' for main:Object

然后,我尝试完全不引用用户,而只是尝试在没有连接的情况下获得所有convo。

Convo.where("Connect.between(? ,?) < ?)", :sender_id, :recipient_id, 1)

# ActiveRecord::StatementInvalid (SQLite3::SQLException: near "between": syntax error: SELECT "convos".* FROM "convos" WHERE (Connect.between('sender_id' ,'recipient_id') < 1)))

Convo.where("Connect.between(? ,?) < ?)", self.sender_id, self.recipient_id, 1)

# NoMethodError (undefined method `sender_id' for main:Object)

在不存在连接的情况下获取所有用户需求的最佳方法是什么?

更新

这是可行的,而且是我要寻找的,但是显然这很浪费,我想了解如何在一次通话中获得此功能。

@og_connections = []
current_user.convos.each do |convo|
   if Connect.between(convo.sender_id, convo.recipient_id).length === 0
     @og_connections.push(current_user.id === convo.sender_id ? convo.recipient_id : convo.sender_id)
   end
end
@connections = User.select(:id, :first_name, :slug).where(id: @og_connections, status: 'Active')
安德鲁·施瓦兹

用当前设置回答

如果你正在寻找的只是current_user,你会想用自己开始convos,做一个左加盟connects,并选择其中的行connectsNULL使用您的表设置,我们将必须对可能的user_id组合进行手动连接:

current_user.convos.joins("
  LEFT JOIN connects ON
    (connects.requestor_id = convos.sender_id AND connects.requestee_id = convos.recipient_id)
    OR
    (connects.requestor_id = convos.recipient_id AND connects.requestee_id = convos.sender_id)
  ").where(connects: {id: nil})

左边的联接为您提供了与convo相同的两个用户之间的任何连接,current_user因为我们从开始就必须涉及current_user.convos从那里,我们筛选下降到仅其中的行connects字段NULL,让我们用行,它一康沃具有匹配的连接。


建议

在Rails应用程序中,大量的原始SQL有点代码味道,这是因为我们试图在此处按原样设置模型来执行这些操作。我建议重构数据模型以简化查询。我想到两个想法:

  1. 始终为connect和convo创建对称记录,因此您可以单列查找而不是使用所有ORs。也就是说,无论何时connect在用户1和用户2之间创建一个,也要在用户2和用户1之间创建一个。更多簿记,因为您还必须一起销毁和编辑它们。但是它可以让你。定义没有所有障碍的简单关联。
  2. 使用单独的表来引用唯一的用户对(顺序无关紧要)。为此,请UserPair使用user_1_id创建一个模型user_2_id,其中user_1_id始终设置为两个用户ID中的较低者。这样一来,convo可以更容易地通过user_pair_idUserPairhas_many :convos和来识别has_many: connects,并且您可以将之间的直线连接起来convos -> user_pairs -> connects

2中的模型看起来像

class UserPair < ApplicationRecord
  belongs_to :user_1, class_name: "User"
  belongs_to :user_2, class_name: "User"

  before_save :sort_users

  scope :between, -> (user_1_id,user_2_id) do
    # records are always saved in sorted id order, so sort before querying
    user_1_id, user_2_id = [user_1_id, user_2_id].sort
    where(user_1_id: user_1_id, user_2_id: user_2_id)
  end

  # always put lowest id first for easy lookup
  def sort_users
    if user_1.present? && user_2.present? && user_1.id > user_2.id
      self.user_1, self.user_2 = user_2, user_1
    end
  end
end

class Convo < ApplicationRecord
  belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
  belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'
  belongs_to :user_pair

  before_validation :set_user_pair

  scope :involving, -> (user) do
    where("convos.sender_id =? OR convos.recipient_id =?",user.id,user.id)
  end

  # since UserPair records are always user_id sorted, we can just use
  # that model's scope here without need to repeat it, using `merge`
  scope :between, -> (sender_id,recipient_id) do
    joins(:user_pair).merge(UserPair.between(sender_id, recipient_id))
  end

  def set_user_pair
    self.user_pair = UserPair.find_or_initialize_by(user_1: sender, user_2: recipient)
  end
end

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将不相关的模型中的查询集序列化为嵌套序列化器?

在路线上加载不相关的模型

Active Record-Rails 6,具有两个不相关模型使用的模型

Laravel 查询两个不相关的模型并返回两者的字段

在循环使用bash中不相关的数字范围时使用文件中的行

如何基于不相关的其他表更改列中的值

来自查询的order_by使不相关的查询失败

在 Linq 中包含不相关的表以进行实体查询

如何合并到不相关表中仅1行的2个查询结果

有没有办法在SQL查询中返回多个不相关的结果?

Microsoft Access:为什么我从不相关的表中查询不起作用?

如何对 SQL 中的每一行在不相关的表上执行查询

如何建立SQL查询选择不相关的项目在Postgres中的多对多关系?

MySQL查询:从两个不相关的表中获取总计

AngularJS正在为不相关的范围变量设置值

预取不相关的任意场等效模型

POJO不相关或不可用时的HQL查询

如何编写附加不相关行的SQL查询?

具有多个不相关表的SQL查询

加入两个不相关的SELECT查询

如何通过单个查询选择不相关的实体

rails 迁移更改了不相关的列

基于另一个不相关表的任何记录中是否存在值的定制输出列

mysql 查询中 2 个不相关表的同一列中的唯一值

用不相关的术语证明不相关的事物

如何消除代码中不相关的输出?

插件管理器中与JMeter不相关的插件

如何在SQL中检查多个不相关的条件?

在Spring Batch Writer中写入多个不相关的表