From a5d3062654bf69098c55e46121ed622d956c19cd Mon Sep 17 00:00:00 2001
From: Manuel Bustillo <bustikiller@bustikiller.com>
Date: Mon, 27 Jan 2025 20:08:28 +0100
Subject: [PATCH] Define and seed an invitation model

---
 app/models/expense.rb                         |  2 +-
 app/models/group.rb                           |  2 +-
 app/models/guest.rb                           | 26 +++++++++++--------
 app/models/invitation.rb                      | 23 ++++++++++++++++
 app/models/seat.rb                            |  2 +-
 app/models/tables_arrangement.rb              |  2 +-
 app/models/user.rb                            |  2 +-
 config/initializers/acts_as_tenant.rb         |  6 ++++-
 .../20250127183547_create_invitations.rb      | 10 +++++++
 ...27190131_fix_cascading_wedding_deletion.rb |  8 ++++++
 db/schema.rb                                  | 25 +++++++++++++-----
 db/seeds.rb                                   |  8 ++----
 spec/factories/invitations.rb                 |  7 +++++
 spec/models/invitation_spec.rb                |  7 +++++
 14 files changed, 100 insertions(+), 30 deletions(-)
 create mode 100644 app/models/invitation.rb
 create mode 100644 db/migrate/20250127183547_create_invitations.rb
 create mode 100644 db/migrate/20250127190131_fix_cascading_wedding_deletion.rb
 create mode 100644 spec/factories/invitations.rb
 create mode 100644 spec/models/invitation_spec.rb

diff --git a/app/models/expense.rb b/app/models/expense.rb
index 66b32f3..a04a5c1 100644
--- a/app/models/expense.rb
+++ b/app/models/expense.rb
@@ -20,7 +20,7 @@
 #
 # Foreign Keys
 #
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class Expense < ApplicationRecord
   acts_as_tenant :wedding
diff --git a/app/models/group.rb b/app/models/group.rb
index 2db28ed..e0db499 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -25,7 +25,7 @@
 # Foreign Keys
 #
 #  fk_rails_...  (parent_id => groups.id)
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class Group < ApplicationRecord
   acts_as_tenant :wedding
diff --git a/app/models/guest.rb b/app/models/guest.rb
index d080679..54142ee 100644
--- a/app/models/guest.rb
+++ b/app/models/guest.rb
@@ -6,28 +6,32 @@
 #
 # Table name: guests
 #
-#  id         :uuid             not null, primary key
-#  name       :string
-#  phone      :string
-#  status     :integer          default("considered")
-#  created_at :datetime         not null
-#  updated_at :datetime         not null
-#  group_id   :uuid
-#  wedding_id :uuid             not null
+#  id            :uuid             not null, primary key
+#  name          :string
+#  phone         :string
+#  status        :integer          default("considered")
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  group_id      :uuid
+#  invitation_id :uuid
+#  wedding_id    :uuid             not null
 #
 # Indexes
 #
-#  index_guests_on_group_id    (group_id)
-#  index_guests_on_wedding_id  (wedding_id)
+#  index_guests_on_group_id       (group_id)
+#  index_guests_on_invitation_id  (invitation_id)
+#  index_guests_on_wedding_id     (wedding_id)
 #
 # Foreign Keys
 #
 #  fk_rails_...  (group_id => groups.id)
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (invitation_id => invitations.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class Guest < ApplicationRecord
   acts_as_tenant :wedding
   belongs_to :group, optional: true
+  belongs_to :invitation, optional: true
 
   enum :status, {
     considered: 0,
diff --git a/app/models/invitation.rb b/app/models/invitation.rb
new file mode 100644
index 0000000..8fb8c1a
--- /dev/null
+++ b/app/models/invitation.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: invitations
+#
+#  id         :uuid             not null, primary key
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#  wedding_id :uuid             not null
+#
+# Indexes
+#
+#  index_invitations_on_wedding_id  (wedding_id)
+#
+# Foreign Keys
+#
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
+#
+class Invitation < ApplicationRecord
+  acts_as_tenant :wedding
+  has_many :guests, dependent: :nullify
+end
diff --git a/app/models/seat.rb b/app/models/seat.rb
index 9c31c42..f4f7b97 100644
--- a/app/models/seat.rb
+++ b/app/models/seat.rb
@@ -24,7 +24,7 @@
 #
 #  fk_rails_...  (guest_id => guests.id)
 #  fk_rails_...  (tables_arrangement_id => tables_arrangements.id) ON DELETE => cascade
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class Seat < ApplicationRecord
   acts_as_tenant :wedding
diff --git a/app/models/tables_arrangement.rb b/app/models/tables_arrangement.rb
index a461555..b5fccb0 100644
--- a/app/models/tables_arrangement.rb
+++ b/app/models/tables_arrangement.rb
@@ -20,7 +20,7 @@
 #
 # Foreign Keys
 #
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class TablesArrangement < ApplicationRecord
   acts_as_tenant :wedding
diff --git a/app/models/user.rb b/app/models/user.rb
index ff46fff..6c7d79c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -32,7 +32,7 @@
 #
 # Foreign Keys
 #
-#  fk_rails_...  (wedding_id => weddings.id)
+#  fk_rails_...  (wedding_id => weddings.id) ON DELETE => cascade
 #
 class User < ApplicationRecord
   acts_as_tenant :wedding
diff --git a/config/initializers/acts_as_tenant.rb b/config/initializers/acts_as_tenant.rb
index fd8890d..25855eb 100644
--- a/config/initializers/acts_as_tenant.rb
+++ b/config/initializers/acts_as_tenant.rb
@@ -2,4 +2,8 @@
 
 ActsAsTenant.configure do |config|
   config.require_tenant = !Rails.env.test?
-end
\ No newline at end of file
+end
+
+Rails.application.console do
+  ActsAsTenant.current_tenant = Wedding.first
+end
diff --git a/db/migrate/20250127183547_create_invitations.rb b/db/migrate/20250127183547_create_invitations.rb
new file mode 100644
index 0000000..ed2e8a3
--- /dev/null
+++ b/db/migrate/20250127183547_create_invitations.rb
@@ -0,0 +1,10 @@
+class CreateInvitations < ActiveRecord::Migration[8.0]
+  def change
+    create_table :invitations, id: :uuid do |t|
+      t.references :wedding, null: false, foreign_key: { on_delete: :cascade }, type: :uuid
+      t.timestamps
+    end
+
+    add_reference :guests, :invitation, foreign_key: true, type: :uuid
+  end
+end
diff --git a/db/migrate/20250127190131_fix_cascading_wedding_deletion.rb b/db/migrate/20250127190131_fix_cascading_wedding_deletion.rb
new file mode 100644
index 0000000..366df85
--- /dev/null
+++ b/db/migrate/20250127190131_fix_cascading_wedding_deletion.rb
@@ -0,0 +1,8 @@
+class FixCascadingWeddingDeletion < ActiveRecord::Migration[8.0]
+  def change
+    [:expenses, :groups, :guests, :seats, :tables_arrangements, :users].each do |table|
+      remove_foreign_key table, column: :wedding_id
+      add_foreign_key table, :weddings, on_delete: :cascade
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5b61f3f..5a7e2fd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[8.0].define(version: 2025_01_26_091823) do
+ActiveRecord::Schema[8.0].define(version: 2025_01_27_190131) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pg_catalog.plpgsql"
 
@@ -63,10 +63,19 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_26_091823) do
     t.integer "status", default: 0
     t.string "name"
     t.uuid "wedding_id", null: false
+    t.uuid "invitation_id"
     t.index ["group_id"], name: "index_guests_on_group_id"
+    t.index ["invitation_id"], name: "index_guests_on_invitation_id"
     t.index ["wedding_id"], name: "index_guests_on_wedding_id"
   end
 
+  create_table "invitations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.uuid "wedding_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["wedding_id"], name: "index_invitations_on_wedding_id"
+  end
+
   create_table "seats", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "guest_id", null: false
     t.uuid "tables_arrangement_id", null: false
@@ -239,22 +248,24 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_26_091823) do
     t.index ["slug"], name: "index_weddings_on_slug", unique: true
   end
 
-  add_foreign_key "expenses", "weddings"
+  add_foreign_key "expenses", "weddings", on_delete: :cascade
   add_foreign_key "group_affinities", "groups", column: "group_a_id"
   add_foreign_key "group_affinities", "groups", column: "group_b_id"
   add_foreign_key "groups", "groups", column: "parent_id"
-  add_foreign_key "groups", "weddings"
+  add_foreign_key "groups", "weddings", on_delete: :cascade
   add_foreign_key "guests", "groups"
-  add_foreign_key "guests", "weddings"
+  add_foreign_key "guests", "invitations"
+  add_foreign_key "guests", "weddings", on_delete: :cascade
+  add_foreign_key "invitations", "weddings", on_delete: :cascade
   add_foreign_key "seats", "guests"
   add_foreign_key "seats", "tables_arrangements", on_delete: :cascade
-  add_foreign_key "seats", "weddings"
+  add_foreign_key "seats", "weddings", on_delete: :cascade
   add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
   add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
   add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
   add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
   add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
   add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
-  add_foreign_key "tables_arrangements", "weddings"
-  add_foreign_key "users", "weddings"
+  add_foreign_key "tables_arrangements", "weddings", on_delete: :cascade
+  add_foreign_key "users", "weddings", on_delete: :cascade
 end
diff --git a/db/seeds.rb b/db/seeds.rb
index fcf5ec3..e7169ab 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -3,11 +3,6 @@
 NUMBER_OF_GUESTS = 50
 
 ActsAsTenant.without_tenant do
-  TablesArrangement.delete_all
-  Expense.delete_all
-  Guest.delete_all
-  Group.delete_all
-  
   Wedding.delete_all
 end
 
@@ -66,7 +61,8 @@ ActsAsTenant.with_tenant(wedding) do
       name: Faker::Name.name,
       phone: Faker::PhoneNumber.cell_phone,
       group: groups.sample,
-      status: Guest.statuses.keys.sample
+      status: Guest.statuses.keys.sample,
+      invitation: (Invitation.create!(wedding:) if rand > 0.1),
     )
   end
 
diff --git a/spec/factories/invitations.rb b/spec/factories/invitations.rb
new file mode 100644
index 0000000..b4ba145
--- /dev/null
+++ b/spec/factories/invitations.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+  factory :invitation do
+    wedding
+  end
+end
diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb
new file mode 100644
index 0000000..24c963e
--- /dev/null
+++ b/spec/models/invitation_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Invitation do
+  pending "add some examples to (or delete) #{__FILE__}"
+end