Rails 7,返回活动记录与两个单独的条件的关联,一个在父项中,一个在子项中

Rails 7, return active record association with two separate conditions, one in the parent, one in the child

提问人:Frub 提问时间:9/20/2023 最后编辑:mechnicovFrub 更新时间:9/20/2023 访问量:60

问:

我有一个模型,它已成为项目所有者和该项目申请人之间的位置或聊天。Applicant

我通过使用表中的参考资料来跟踪申请人。applicant.userApplicant

我使用 跟踪项目所有者,这是表中的引用(的父级)。applicant.project.userProjectApplicant

正如我所说,该表还有一个子 ,本质上是两个用户之间的聊天视图。ApplicantMessagesApplicant

用户使用 Devise 进行管理。

“申请人”表中要提到的另一个字段是一个字段,每当用户为该记录创建新邮件时,该字段就会更新。last_messageApplicant

class Applicant < ApplicationRecord
  belongs_to :project
  belongs_to :user
  has_many :messages, dependent: :destroy
end
class Project < ApplicationRecord
  belongs_to :user
  has_many :applicants, dependent: :destroy
  has_rich_text :description
end
class User < ApplicationRecord
  has_many :projects, dependent: :destroy
  has_many :applicants, dependent: :destroy
  has_rich_text :about

  devise :database_authenticatable, :registerable, :confirmable, :trackable,
         :recoverable, :rememberable, :validatable
end
class Message < ApplicationRecord
  belongs_to :applicant
end

我想获取任何用户“聊天”(或申请人)的列表。这既是他们的项目,也是他们的申请人。

我目前正在这样做:

project_messages = []

current_user.projects.each do |project|
  project.applicants.each do |applicant|
    project_messages << applicant
  end
end

@chats = Applicant
  .where(id: (current_user.applicants + project_messages)
  .map(&:id))
  .order(last_message: :desc)

在这里,我得到了一个current_user项目的列表,并将每个申请人(聊天室)添加到一个数组中。然后,我将其添加到current_user.applicants中。然后,我将两者合并为活动记录关联。

这可行,但我觉得这样做是一种糟糕的方法。有谁知道更有效的方法?

Ruby-on-Rails 设计 Ruby-On-Rails-7

评论

0赞 Frub 9/20/2023
@mechnicov当然,现在添加了它们

答:

1赞 mechnicov 9/20/2023 #1

您可以联接申请人和项目表,并检查当前用户是否是申请人或项目“所有者”,如下所示

applicants =
  Applicant
    .joins(:project)
    .where('applicants.user_id = :id OR projects.user_id = :id', id: current_user.id)
    .order(last_message: :desc)
0赞 Fahad Abbas 9/20/2023 #2

好吧,您可以跳过循环,并且可以在用户模型中添加自定义关联,例如

class User
  has_many :other_chats, through: :projects, class_name: "Applicant"
end

然后,您可以使用查询所有聊天记录

@chats = Applicant
  .where(id: (current_user.applicants + other_chats)
  .map(&:id)).order(last_message: :desc)

评论

0赞 mechnicov 9/20/2023
可能是未定义的方法或变量错误。将执行三个查询。而且可能如果有大量的申请人,并且效率不会那么高other_chats+map