列の値に基づいたカスタム has_one
概要
Rails の初心者は、ActiveRecords を使用してこの関係をモデル化できるかどうか疑問に思っていました。
次のモデルがあります(簡略化):
User:
- name
- email
Client:
- name
- address
そして、これらのテーブルの両方に関連するモデルの出席者がありますが、type 列があります。
| id | join_type | join_id |
|----|-----------|---------|
| 1 | user | 1 |
| 2 | client | 1 |
has_one リレーションを使用してアクティブなレコードでそれをモデル化する方法はありますか?
何かのようなもの:
class Attendee < ApplicationRecord
# OBVIOUSLY DOESNT WORK
has_one :user, ->() { where(join_type: 'user') }, :class_name => 'User'
has_one :client, ->() { where(join_type: 'client') }, :class_name => 'Client'
end
つまり、正しい左結合が生成されるのでしょうか?
ありがとう
解決策
この構造で出席者テーブルを作成します
class CreateAttendees < ActiveRecord::Migration[7.0]
def change
create_table :attendees do |t|
t.timestamps
t.string :linked_object_type
t.bigint :linked_object_id
end
# optinal
add_index :attendees, %i[linked_object_type linked_object_id]
end
end
# app/models/client_attendee.rb
class Attendee < ApplicationRecord
belongs_to :linked_object, polymorphic: true, foreign_type: :linked_object_type
end
次に、次のようにAttendeeインスタンスからユーザー/クライアントにアクセスできます
attendee = Attendee.first
linked_object = attendee.linked_object # Depends on linked object type it will return the relative model instance
ユーザー/顧客から出席者にアクセスしたい場合は、次のように定義できます。
# frozen_string_literal: true
# This model is used to store user data
class User < ApplicationRecord
has_many :attendees, as: :linked_object, linked_object_type: 'User' # You can scope it yourself, and define has_one depends on your design.
end