You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中用户、页面所有者与访客的关联数据库设计求助

Alright, let's work through a normalized database schema for your page ownership and visitor invitation system. This structure is flexible, scalable, and covers all your core requirements:

Core Table Structure

1. users Table

Stores all registered users in your system.

Column NameData TypeDescription
user_idINT (PK, AUTO_INCREMENT)Unique identifier for each user (primary key)
usernameVARCHAR(50)Unique display name/username (enforce uniqueness)
emailVARCHAR(100)User's email address (used for invitations, enforce uniqueness)
password_hashVARCHAR(255)Hashed password (never store plain text!)
created_atDATETIMETimestamp when the user account was created
updated_atDATETIMETimestamp when the user account was last updated

2. pages Table

Stores all website pages, with a direct link to their owner.

Column NameData TypeDescription
page_idINT (PK, AUTO_INCREMENT)Unique identifier for each page
page_nameVARCHAR(100)Name/title of the page
page_slugVARCHAR(100)URL-friendly version of the page name (unique, used for routing)
owner_idINT (FK)Links to users.user_id - identifies the page's creator/owner
created_atDATETIMETimestamp when the page was created
updated_atDATETIMETimestamp when the page details were last updated

Key Constraint: Add a foreign key on owner_id referencing users.user_id with ON DELETE CASCADE (adjust to ON DELETE SET NULL if you want to retain pages without an owner instead).

3. page_invitations Table

Tracks all sent invitations for users to join a page. This handles the pending state before a user accepts or rejects the invite.

Column NameData TypeDescription
invitation_idINT (PK, AUTO_INCREMENT)Unique identifier for each invitation
page_idINT (FK)Links to pages.page_id - the page the invitation is for
sender_idINT (FK)Links to users.user_id - the user who sent the invitation (usually the page owner, but you can extend this to allow other members later if needed)
recipient_idINT (FK)Links to users.user_id - the user being invited
statusENUM('pending', 'accepted', 'rejected', 'expired')Current state of the invitation
invited_atDATETIMETimestamp when the invitation was sent
responded_atDATETIMETimestamp when the recipient responded (null until they accept/reject)

Unique Constraint: Add a composite unique key on (page_id, recipient_id) to prevent duplicate invitations to the same user for the same page.

Foreign Keys:

  • page_id references pages.page_id (ON DELETE CASCADE: if the page is deleted, delete all related invitations)
  • sender_id and recipient_id reference users.user_id (ON DELETE CASCADE: if a user is deleted, remove their sent/received invitations)

4. page_members Table

Stores all active members of a page, including the owner and accepted visitors. Using a separate table makes it easy to query who has access to a page at any time.

Column NameData TypeDescription
member_idINT (PK, AUTO_INCREMENT)Unique identifier for each page membership
page_idINT (FK)Links to pages.page_id
user_idINT (FK)Links to users.user_id
roleENUM('owner', 'visitor')The user's role on the page (owner has full control, visitor has read/limited access)
joined_atDATETIMETimestamp when the user became a member

Unique Constraint: Composite unique key on (page_id, user_id) to ensure a user can't be added to the same page multiple times.

Foreign Keys:

  • page_id references pages.page_id (ON DELETE CASCADE: remove members if the page is deleted)
  • user_id references users.user_id (ON DELETE CASCADE: remove memberships if the user is deleted)

Business Logic Flow

Here's how the tables work together in practice:

  • When a user creates a page:
    1. Insert a new record into pages with owner_id set to the creator's user_id.
    2. Automatically insert a record into page_members for the creator with role = 'owner'.
  • When an owner sends an invitation:
    1. Insert a new record into page_invitations with status = 'pending'.
  • When the recipient accepts the invitation:
    1. Update the corresponding page_invitations record to status = 'accepted' and set responded_at.
    2. Insert a new record into page_members with role = 'visitor'.
  • If the recipient rejects the invitation:
    1. Update the page_invitations record to status = 'rejected' and set responded_at.

Index Recommendations

To optimize common queries (like fetching all members of a page, or pending invitations for a user):

  • Add indexes on pages.owner_id
  • Add indexes on page_invitations.recipient_id and page_invitations.page_id
  • Add indexes on page_members.page_id and page_members.user_id

This schema keeps things organized, avoids data duplication, and gives you room to extend functionality later (like adding different visitor roles, or allowing owners to revoke access).

内容的提问来源于stack exchange,提问作者Sourabh Banka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:10:50