基于Gather模型构建自定义好友关联的技术咨询
问题描述
我一直在研究基于角色、自定义关联的好友模型,但没法把它和我的项目清晰结合。需求如下:
- User可以创建名为Gather的活动,也能参与他人创建的Gather
- 参与活动的User即为Gatherer,Gatherer列表会被视为活动创建者的好友
当前已完成的模型代码
User模型
class User < ApplicationRecord has_many :gathers_as_creator, foreign_key: :creator_id, class_name: :Gather has_many :gathers_as_gatherer, foreign_key: :gatherer_id, class_name: :Gather end
Gather模型
class Gather < ApplicationRecord belongs_to :creator, class_name: :User belongs_to :gatherer, class_name: :User end
疑问与构想
我现在的疑问是:是否需要Gatherer这样的关联表来支持多参与者,以便后续为用户/创建者获取好友列表?
我构想的Gatherer模型及表结构如下:
Gatherer模型
belongs_to :gather_attendee, class_name: "User" belongs_to :attended_gather, class_name: "Gather"
表结构
create_table "gatherers", force: :cascade do |t| t.bigint "attended_gather_id" t.bigint "gather_attendee_id" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["attended_gather_id"], name: "index_gatherers_on_attended_gather_id" t.index ["gather_attendee_id"], name: "index_gatherers_on_gather_attendee_id" end
之前的规划代码
我还有之前的完整Schema及模型代码,现在理不清关联关系,希望得到指导。
Schema
create_table "activities", force: :cascade do |t| t.string "a_type" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "gatherers", force: :cascade do |t| t.bigint "attended_gather_id" t.bigint "gather_attendee_id" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["attended_gather_id"], name: "index_gatherers_on_attended_gather_id" t.index ["gather_attendee_id"], name: "index_gatherers_on_gather_attendee_id" end create_table "gathers", force: :cascade do |t| t.integer "creator_id" t.integer "activity_id" t.text "gather_point" t.boolean "active" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "interest_gathers", force: :cascade do |t| t.string "gather_id" t.string "interest_id" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "interests", force: :cascade do |t| t.string "i_type" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end create_table "users", force: :cascade do |t| t.string "username" t.string "img" t.string "first_name" t.string "last_name" t.string "state" t.string "city" t.string "bio" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end add_foreign_key "gatherers", "gathers", column: "attended_gather_id" add_foreign_key "gatherers", "users", column: "gather_attendee_id" end
User模型
class User < ActiveRecord::Base has_many :gatherers, foreign_key: gather_attendee_id has_many :attended_gathers, through: :gatherers has_many :created_gathers, foreign_key: :creator_id, class_name: "Gather" end
Gather模型
class Gather < ActiveRecord::Base has_many :gatherers, foreign_key: :attended_gather_id has_many :attendees, through: :gatherers, source: :gather_attendee belongs_to :creator, class_name: "User" end
Gatherer模型
class Gatherer < ActiveRecord::Base belongs_to :gather_attendee, class_name: "User" belongs_to :attended_gather, class_name: "Gather" end
解答
首先,你当前的Gather模型设计存在核心问题:belongs_to :gatherer 意味着一个Gather只能绑定单个参与者,完全不符合“多用户参与活动”的需求。因此**必须引入Gatherer关联表(多对多中间表)**来实现活动与多参与者的对应关系。
以下是梳理后的正确关联关系和优化说明:
修正后的模型关联
User模型
class User < ApplicationRecord # 用户创建的所有活动 has_many :created_gathers, foreign_key: :creator_id, class_name: "Gather" # 用户参与的活动(通过中间表关联) has_many :gatherers, foreign_key: :gather_attendee_id has_many :attended_gathers, through: :gatherers, source: :attended_gather # 直接获取好友列表:所有参与过自己创建活动的用户 has_many :friends, through: :created_gathers, source: :attendees end
Gather模型
class Gather < ApplicationRecord belongs_to :creator, class_name: "User" # 活动的所有参与者(通过中间表关联) has_many :gatherers, foreign_key: :attended_gather_id has_many :attendees, through: :gatherers, source: :gather_attendee end
Gatherer模型
class Gatherer < ApplicationRecord belongs_to :gather_attendee, class_name: "User" belongs_to :attended_gather, class_name: "Gather" end
关键说明
- 多对多关系实现:Gather和User的参与关系是典型的多对多,必须通过Gatherer中间表承载,这样一个活动可以有多个参与者,一个用户也能参与多个活动。
- 好友列表快速获取:通过
has_many :friends, through: :created_gathers, source: :attendees,可以直接调用user.friends获取所有参与过该用户创建活动的用户,完美匹配需求。 - Schema优化点:之前的Schema中,
gathers表的creator_id需改为bigint(与users表id类型一致),interest_gathers表的gather_id和interest_id也应改为bigint并添加外键约束,避免类型不匹配导致的潜在问题。
内容的提问来源于stack exchange,提问作者Josette Garcia
相关产品推荐
相关产品推荐

