Techioz Blog

Rails 7、2 つの個別の条件 (親に 1 つ、子に 1 つ) を使用してアクティブなレコードの関連付けを返します。

概要

申請者モデルがあります。これは、プロジェクト所有者とそのプロジェクトへの申請者間の場所またはチャットになります。

申請者テーブルの applicant.user 参照を使用して申請者を追跡します。

applicant.project.user を使用してプロジェクト所有者を追跡します。これは、Project テーブル (Applicant の親) 内の参照です。

先ほども言いましたが、Applicant テーブルには Messages の子もあり、Applicant は基本的に 2 人のユーザー間のチャット ビューです。

ユーザーは Devise を使用して管理されます。

Applicant テーブルで言及すべきもう 1 つのフィールドは、ユーザーがその Applicant レコードに対して新しいメッセージを作成するたびに更新される last_message フィールドです。

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 に追加します。次に、両方をアクティブなレコードの関連付けとしてマージします。

これは機能しますが、これは悪い方法だと感じます。誰かこれを行うより効率的な方法を知っていますか?

解決策

次のように、応募者とプロジェクトのテーブルを結合して、現在のユーザーが応募者であるかプロジェクトの「所有者」であるかを確認できます。

applicants =
  Applicant
    .joins(:project)
    .where('applicants.user_id = :id OR projects.user_id = :id', id: current_user.id)
    .order(last_message: :desc)