Merge pull request 'Make the application multi-tenant based on a wedding model' (#153) from wedding-model into main
Reviewed-on: #153
This commit is contained in:
commit
e6cf0da814
1
Gemfile
1
Gemfile
@ -20,6 +20,7 @@ gem 'jsonapi-rails'
|
||||
gem 'rack-cors'
|
||||
gem 'react-rails'
|
||||
gem 'rubytree'
|
||||
gem 'acts_as_tenant'
|
||||
|
||||
group :development, :test do
|
||||
gem 'annotaterb'
|
||||
|
@ -72,6 +72,8 @@ GEM
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
acts_as_tenant (1.0.1)
|
||||
rails (>= 6.0)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
annotaterb (4.13.0)
|
||||
@ -387,6 +389,7 @@ PLATFORMS
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
acts_as_tenant
|
||||
annotaterb
|
||||
bootsnap
|
||||
chroma
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
before_action :set_tenant
|
||||
before_action :authenticate_user!
|
||||
after_action :set_csrf_cookie
|
||||
|
||||
@ -29,6 +30,10 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
private
|
||||
|
||||
def set_tenant
|
||||
ActsAsTenant.current_tenant = Wedding.find_by(slug: params[:slug])
|
||||
end
|
||||
|
||||
def development_swagger?
|
||||
Rails.env.test? ||
|
||||
Rails.env.development? && request.headers['referer']&.include?('/api-docs/index.html')
|
||||
|
@ -3,21 +3,23 @@
|
||||
class TableSimulatorJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(*_args)
|
||||
engine = VNS::Engine.new
|
||||
def perform(wedding_id)
|
||||
ActsAsTenant.with_tenant(Wedding.find(wedding_id)) do
|
||||
engine = VNS::Engine.new
|
||||
|
||||
engine.add_perturbation(Tables::Swap)
|
||||
engine.add_perturbation(Tables::Shift)
|
||||
engine.add_perturbation(Tables::Swap)
|
||||
engine.add_perturbation(Tables::Shift)
|
||||
|
||||
initial_solution = Tables::Distribution.new(min_per_table: 8, max_per_table: 10)
|
||||
initial_solution.random_distribution(Guest.potential.shuffle)
|
||||
initial_solution = Tables::Distribution.new(min_per_table: 8, max_per_table: 10)
|
||||
initial_solution.random_distribution(Guest.potential.shuffle)
|
||||
|
||||
engine.initial_solution = initial_solution
|
||||
engine.initial_solution = initial_solution
|
||||
|
||||
engine.target_function(&:discomfort)
|
||||
engine.target_function(&:discomfort)
|
||||
|
||||
best_solution = engine.run
|
||||
best_solution = engine.run
|
||||
|
||||
best_solution.save!
|
||||
best_solution.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,8 +10,18 @@
|
||||
# pricing_type :enum default("fixed"), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_expenses_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class Expense < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
enum :pricing_type,
|
||||
fixed: 'fixed',
|
||||
per_person: 'per_person'
|
||||
|
@ -12,17 +12,22 @@
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# parent_id :uuid
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_groups_on_name (name) UNIQUE
|
||||
# index_groups_on_parent_id (parent_id)
|
||||
# index_groups_on_name (name) UNIQUE
|
||||
# index_groups_on_parent_id (parent_id)
|
||||
# index_groups_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (parent_id => groups.id)
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class Group < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
|
||||
validates :name, uniqueness: true
|
||||
validates :name, :order, presence: true
|
||||
|
||||
|
@ -11,16 +11,20 @@
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# group_id :uuid not null
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_guests_on_group_id (group_id)
|
||||
# index_guests_on_group_id (group_id)
|
||||
# index_guests_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (group_id => groups.id)
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class Guest < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
belongs_to :group
|
||||
|
||||
enum :status, {
|
||||
@ -45,6 +49,6 @@ class Guest < ApplicationRecord
|
||||
def recalculate_simulations
|
||||
TablesArrangement.delete_all
|
||||
|
||||
ActiveJob.perform_all_later(50.times.map { TableSimulatorJob.new })
|
||||
ActiveJob.perform_all_later(50.times.map { TableSimulatorJob.new(wedding_id) })
|
||||
end
|
||||
end
|
||||
|
@ -10,18 +10,22 @@
|
||||
# updated_at :datetime not null
|
||||
# guest_id :uuid not null
|
||||
# tables_arrangement_id :uuid not null
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_seats_on_guest_id (guest_id)
|
||||
# index_seats_on_tables_arrangement_id (tables_arrangement_id)
|
||||
# index_seats_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (guest_id => guests.id)
|
||||
# fk_rails_... (tables_arrangement_id => tables_arrangements.id) ON DELETE => cascade
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class Seat < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
belongs_to :guest
|
||||
belongs_to :table_arrangement
|
||||
end
|
||||
|
@ -9,8 +9,18 @@
|
||||
# name :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_tables_arrangements_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class TablesArrangement < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
has_many :seats
|
||||
has_many :guests, through: :seats
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
# unlock_token :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# wedding_id :uuid not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@ -25,8 +26,15 @@
|
||||
# index_users_on_email (email) UNIQUE
|
||||
# index_users_on_reset_password_token (reset_password_token) UNIQUE
|
||||
# index_users_on_unlock_token (unlock_token) UNIQUE
|
||||
# index_users_on_wedding_id (wedding_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (wedding_id => weddings.id)
|
||||
#
|
||||
class User < ApplicationRecord
|
||||
acts_as_tenant :wedding
|
||||
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :validatable, :confirmable, :lockable
|
||||
end
|
||||
|
20
app/models/wedding.rb
Normal file
20
app/models/wedding.rb
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: weddings
|
||||
#
|
||||
# id :uuid not null, primary key
|
||||
# date :date not null
|
||||
# slug :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_weddings_on_slug (slug) UNIQUE
|
||||
#
|
||||
class Wedding < ApplicationRecord
|
||||
validates :date, presence: true
|
||||
validates :slug, presence: true, uniqueness: true
|
||||
end
|
@ -2,26 +2,30 @@
|
||||
|
||||
Rails.application.routes.draw do
|
||||
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
|
||||
devise_for :users, skip: [:registration, :session, :confirmation]
|
||||
devise_scope :user do
|
||||
post 'users', to: 'users/registrations#create'
|
||||
scope ":slug", constraints: {slug: /[a-z]+/} do
|
||||
devise_for :users, skip: [:registration, :session, :confirmation]
|
||||
devise_scope :user do
|
||||
post 'users', to: 'users/registrations#create'
|
||||
|
||||
post '/users/sign_in', to: 'users/sessions#create'
|
||||
delete '/users/sign_out', to: 'users/sessions#destroy'
|
||||
post '/users/sign_in', to: 'users/sessions#create'
|
||||
delete '/users/sign_out', to: 'users/sessions#destroy'
|
||||
|
||||
get '/users/confirmation', to: 'users/confirmations#show', as: :confirmation
|
||||
get '/users/confirmation', to: 'users/confirmations#show', as: :confirmation
|
||||
end
|
||||
|
||||
resources :groups, only: :index
|
||||
resources :guests, only: %i[index create update destroy] do
|
||||
post :bulk_update, on: :collection
|
||||
end
|
||||
resources :expenses, only: %i[index update] do
|
||||
get :summary, on: :collection
|
||||
end
|
||||
resources :tables_arrangements, only: %i[index show]
|
||||
end
|
||||
|
||||
|
||||
mount Rswag::Ui::Engine => '/api-docs'
|
||||
mount Rswag::Api::Engine => '/api-docs'
|
||||
resources :groups, only: :index
|
||||
resources :guests, only: %i[index create update destroy] do
|
||||
post :bulk_update, on: :collection
|
||||
end
|
||||
resources :expenses, only: %i[index update] do
|
||||
get :summary, on: :collection
|
||||
end
|
||||
resources :tables_arrangements, only: %i[index show]
|
||||
|
||||
get 'up' => 'rails/health#show', as: :rails_health_check
|
||||
|
||||
|
12
db/migrate/20241130182228_create_weddings.rb
Normal file
12
db/migrate/20241130182228_create_weddings.rb
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
class CreateWeddings < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
create_table :weddings, id: :uuid do |t|
|
||||
t.string :slug, null: false, index: { unique: true }
|
||||
t.date :date, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
9
db/migrate/20241130185731_add_wedding_id_to_models.rb
Normal file
9
db/migrate/20241130185731_add_wedding_id_to_models.rb
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
class AddWeddingIdToModels < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
[:expenses, :guests, :seats, :tables_arrangements, :groups, :users].each do |table|
|
||||
add_reference table, :wedding, type: :uuid, null: false, foreign_key: true
|
||||
end
|
||||
end
|
||||
end
|
28
db/schema.rb
generated
28
db/schema.rb
generated
@ -12,7 +12,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2024_11_30_185731) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
@ -26,6 +26,8 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.enum "pricing_type", default: "fixed", null: false, enum_type: "pricing_types"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["wedding_id"], name: "index_expenses_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "groups", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
@ -36,8 +38,10 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.uuid "parent_id"
|
||||
t.string "color"
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["name"], name: "index_groups_on_name", unique: true
|
||||
t.index ["parent_id"], name: "index_groups_on_parent_id"
|
||||
t.index ["wedding_id"], name: "index_groups_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "guests", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
@ -47,7 +51,9 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.uuid "group_id", null: false
|
||||
t.integer "status", default: 0
|
||||
t.string "name"
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["group_id"], name: "index_guests_on_group_id"
|
||||
t.index ["wedding_id"], name: "index_guests_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "seats", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
@ -56,8 +62,10 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.integer "table_number"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["guest_id"], name: "index_seats_on_guest_id"
|
||||
t.index ["tables_arrangement_id"], name: "index_seats_on_tables_arrangement_id"
|
||||
t.index ["wedding_id"], name: "index_seats_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "solid_queue_blocked_executions", force: :cascade do |t|
|
||||
@ -186,6 +194,8 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "name", null: false
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["wedding_id"], name: "index_tables_arrangements_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
@ -202,20 +212,36 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_30_095753) do
|
||||
t.datetime "locked_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.uuid "wedding_id", null: false
|
||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
|
||||
t.index ["wedding_id"], name: "index_users_on_wedding_id"
|
||||
end
|
||||
|
||||
create_table "weddings", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "slug", null: false
|
||||
t.date "date", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["slug"], name: "index_weddings_on_slug", unique: true
|
||||
end
|
||||
|
||||
add_foreign_key "expenses", "weddings"
|
||||
add_foreign_key "groups", "groups", column: "parent_id"
|
||||
add_foreign_key "groups", "weddings"
|
||||
add_foreign_key "guests", "groups"
|
||||
add_foreign_key "guests", "weddings"
|
||||
add_foreign_key "seats", "guests"
|
||||
add_foreign_key "seats", "tables_arrangements", on_delete: :cascade
|
||||
add_foreign_key "seats", "weddings"
|
||||
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"
|
||||
end
|
||||
|
119
db/seeds.rb
119
db/seeds.rb
@ -7,71 +7,76 @@ Expense.delete_all
|
||||
Guest.delete_all
|
||||
Group.delete_all
|
||||
|
||||
Expense.create!(name: 'Photographer', amount: 3000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Country house', amount: 6000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Catering', amount: 200, pricing_type: 'per_person')
|
||||
Expense.create!(name: 'Flowers', amount: 500, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Band', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Wedding planner', amount: 2000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Dress', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Suit', amount: 500, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Rings', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Makeup', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Hair', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Transportation', amount: 3000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Invitations', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Cake', amount: 500, pricing_type: 'fixed')
|
||||
Wedding.delete_all
|
||||
wedding = Wedding.create!(slug: :default, date: 1.year.from_now)
|
||||
|
||||
Group.create!(name: "Jim's guests", icon: 'pi pi-heart').tap do |parent|
|
||||
parent.children.create!(name: "Jim's family", icon: 'pi pi-users').tap do |family|
|
||||
family.children.create!(name: "Jim's close family", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Jim's cousins", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Jim's relatives", icon: 'pi pi-home')
|
||||
ActsAsTenant.with_tenant(wedding) do
|
||||
Expense.create!(name: 'Photographer', amount: 3000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Country house', amount: 6000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Catering', amount: 200, pricing_type: 'per_person')
|
||||
Expense.create!(name: 'Flowers', amount: 500, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Band', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Wedding planner', amount: 2000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Dress', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Suit', amount: 500, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Rings', amount: 1000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Makeup', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Hair', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Transportation', amount: 3000, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Invitations', amount: 200, pricing_type: 'fixed')
|
||||
Expense.create!(name: 'Cake', amount: 500, pricing_type: 'fixed')
|
||||
|
||||
Group.create!(name: "Jim's guests", icon: 'pi pi-heart').tap do |parent|
|
||||
parent.children.create!(name: "Jim's family", icon: 'pi pi-users').tap do |family|
|
||||
family.children.create!(name: "Jim's close family", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Jim's cousins", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Jim's relatives", icon: 'pi pi-home')
|
||||
end
|
||||
parent.children.create!(name: "Jim's friends", icon: 'pi pi-bullseye')
|
||||
parent.children.create!(name: "Jim's work", icon: 'pi pi-desktop').tap do |work|
|
||||
work.children.create!(name: "Jim's besties at work", icon: 'pi pi-briefcase')
|
||||
end
|
||||
end
|
||||
parent.children.create!(name: "Jim's friends", icon: 'pi pi-bullseye')
|
||||
parent.children.create!(name: "Jim's work", icon: 'pi pi-desktop').tap do |work|
|
||||
work.children.create!(name: "Jim's besties at work", icon: 'pi pi-briefcase')
|
||||
|
||||
Group.create!(name: "Pam's guests", icon: 'pi pi-heart-fill').tap do |parent|
|
||||
parent.children.create!(name: "Pam's family", icon: 'pi pi-users').tap do |family|
|
||||
family.children.create!(name: "Pam's close family", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Pam's cousins", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Pam's relatives", icon: 'pi pi-home')
|
||||
end
|
||||
parent.children.create!(name: "Pam's friends", icon: 'pi pi-bullseye')
|
||||
parent.children.create!(name: "Pam's work", icon: 'pi pi-desktop').tap do |work|
|
||||
work.children.create!(name: "Pam's besties at work", icon: 'pi pi-briefcase')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Group.create!(name: "Pam's guests", icon: 'pi pi-heart-fill').tap do |parent|
|
||||
parent.children.create!(name: "Pam's family", icon: 'pi pi-users').tap do |family|
|
||||
family.children.create!(name: "Pam's close family", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Pam's cousins", icon: 'pi pi-home')
|
||||
family.children.create!(name: "Pam's relatives", icon: 'pi pi-home')
|
||||
Group.create!(name: 'Common guests', icon: 'pi pi-users').tap do |parent|
|
||||
parent.children.create!(name: 'College friends', icon: 'pi pi-calculator')
|
||||
parent.children.create!(name: 'High school friends', icon: 'pi pi-crown')
|
||||
parent.children.create!(name: 'Childhood friends', icon: 'pi pi-envelope')
|
||||
end
|
||||
parent.children.create!(name: "Pam's friends", icon: 'pi pi-bullseye')
|
||||
parent.children.create!(name: "Pam's work", icon: 'pi pi-desktop').tap do |work|
|
||||
work.children.create!(name: "Pam's besties at work", icon: 'pi pi-briefcase')
|
||||
|
||||
groups = Group.all
|
||||
|
||||
NUMBER_OF_GUESTS.times do
|
||||
Guest.create!(
|
||||
name: Faker::Name.name,
|
||||
phone: Faker::PhoneNumber.cell_phone,
|
||||
group: groups.sample,
|
||||
status: Guest.statuses.keys.sample
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Group.create!(name: 'Common guests', icon: 'pi pi-users').tap do |parent|
|
||||
parent.children.create!(name: 'College friends', icon: 'pi pi-calculator')
|
||||
parent.children.create!(name: 'High school friends', icon: 'pi pi-crown')
|
||||
parent.children.create!(name: 'Childhood friends', icon: 'pi pi-envelope')
|
||||
end
|
||||
ActiveJob.perform_all_later(3.times.map { TableSimulatorJob.new(wedding.id) })
|
||||
|
||||
groups = Group.all
|
||||
'red'.paint.palette.triad(as: :hex).zip(Group.roots).each { |(color, group)| group.update!(color: color.paint.desaturate(40)) }
|
||||
|
||||
NUMBER_OF_GUESTS.times do
|
||||
Guest.create!(
|
||||
name: Faker::Name.name,
|
||||
phone: Faker::PhoneNumber.cell_phone,
|
||||
group: groups.sample,
|
||||
status: Guest.statuses.keys.sample
|
||||
Group.roots.each(&:colorize_children)
|
||||
|
||||
User.create!(
|
||||
email: 'development@example.com',
|
||||
confirmed_at: Time.zone.now,
|
||||
password: 'supersecretpassword',
|
||||
password_confirmation: 'supersecretpassword',
|
||||
)
|
||||
end
|
||||
|
||||
ActiveJob.perform_all_later(3.times.map { TableSimulatorJob.new })
|
||||
|
||||
'red'.paint.palette.triad(as: :hex).zip(Group.roots).each { |(color, group)| group.update!(color: color.paint.desaturate(40)) }
|
||||
|
||||
Group.roots.each(&:colorize_children)
|
||||
|
||||
User.create!(
|
||||
email: 'development@example.com',
|
||||
confirmed_at: Time.zone.now,
|
||||
password: 'supersecretpassword',
|
||||
password_confirmation: 'supersecretpassword',
|
||||
)
|
@ -2,6 +2,7 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :expense do
|
||||
wedding
|
||||
sequence(:name) { |i| "Expense #{i}" }
|
||||
pricing_type { "fixed" }
|
||||
amount { 100 }
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :group do
|
||||
wedding
|
||||
sequence(:name) { |i| "Group #{i}" }
|
||||
order { 1 }
|
||||
end
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :guest do
|
||||
association :group
|
||||
group
|
||||
wedding
|
||||
|
||||
name { Faker::Name.name }
|
||||
phone { Faker::PhoneNumber.cell_phone }
|
||||
|
8
spec/factories/table_arrangement.rb
Normal file
8
spec/factories/table_arrangement.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
FactoryBot.define do
|
||||
factory :tables_arrangement do
|
||||
wedding
|
||||
end
|
||||
end
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :user do
|
||||
|
||||
wedding
|
||||
end
|
||||
end
|
||||
|
8
spec/factories/weddings.rb
Normal file
8
spec/factories/weddings.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
FactoryBot.define do
|
||||
factory :wedding do
|
||||
sequence(:slug) { |i| "wedding-#{i}" }
|
||||
date { 1.year.from_now }
|
||||
end
|
||||
end
|
@ -5,7 +5,7 @@ require 'rails_helper'
|
||||
RSpec.describe TablesArrangement, type: :model do
|
||||
describe 'callbacks' do
|
||||
it 'assigns a name before creation' do
|
||||
expect(described_class.create!.name).to be_present
|
||||
expect(create(:tables_arrangement).name).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
7
spec/models/wedding_spec.rb
Normal file
7
spec/models/wedding_spec.rb
Normal file
@ -0,0 +1,7 @@
|
||||
# Copyright (C) 2024 Manuel Bustillo
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Wedding, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
@ -3,10 +3,12 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'expenses', type: :request do
|
||||
path '/expenses' do
|
||||
path '/{slug}/expenses' do
|
||||
get('list expenses') do
|
||||
tags 'Expenses'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
|
||||
response(200, 'successful') do
|
||||
schema type: :array,
|
||||
items: {
|
||||
@ -26,12 +28,13 @@ RSpec.describe 'expenses', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
path '/expenses/{id}' do
|
||||
path '/{slug}/expenses/{id}' do
|
||||
|
||||
patch('update expense') do
|
||||
tags 'Expenses'
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: 'id', in: :path, type: :string, format: :uuid, description: 'id'
|
||||
parameter name: :body, in: :body, schema: {
|
||||
type: :object,
|
||||
|
@ -3,10 +3,11 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'groups', type: :request do
|
||||
path '/groups' do
|
||||
path '/{slug}/groups' do
|
||||
get('list groups') do
|
||||
tags 'Groups'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
response(200, 'successful') do
|
||||
schema type: :array,
|
||||
items: {
|
||||
|
@ -3,10 +3,11 @@
|
||||
require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'guests', type: :request do
|
||||
path '/guests' do
|
||||
path '/{slug}/guests' do
|
||||
get('list guests') do
|
||||
tags 'Guests'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
response(200, 'successful') do
|
||||
schema type: :array,
|
||||
items: {
|
||||
@ -33,6 +34,7 @@ RSpec.describe 'guests', type: :request do
|
||||
tags 'Guests'
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: :body, in: :body, schema: {
|
||||
type: :object,
|
||||
required: %i[guest],
|
||||
@ -55,11 +57,12 @@ RSpec.describe 'guests', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
path '/guests/{id}' do
|
||||
path '/{slug}/guests/{id}' do
|
||||
patch('update guest') do
|
||||
tags 'Guests'
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: 'id', in: :path, type: :string, format: :uuid
|
||||
parameter name: :body, in: :body, schema: {
|
||||
type: :object,
|
||||
@ -85,6 +88,7 @@ RSpec.describe 'guests', type: :request do
|
||||
delete('delete guest') do
|
||||
tags 'Guests'
|
||||
produces 'application/json'
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: 'id', in: :path, type: :string, format: :uuid
|
||||
|
||||
response_empty_200
|
||||
|
@ -9,5 +9,13 @@ module Swagger
|
||||
updated_at: SwaggerResponseHelper::TIMESTAMP
|
||||
|
||||
}
|
||||
|
||||
SLUG = {
|
||||
name: 'slug',
|
||||
in: :path,
|
||||
type: :string,
|
||||
example: :default,
|
||||
description: 'Wedding slug'
|
||||
}
|
||||
end
|
||||
end
|
@ -4,11 +4,12 @@ require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'users/confirmations', type: :request do
|
||||
|
||||
path '/users/confirmation' do
|
||||
path '/{slug}/users/confirmation' do
|
||||
get('confirm user email') do
|
||||
tags 'Users'
|
||||
produces 'application/json'
|
||||
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: :confirmation_token, in: :query, type: :string, required: true
|
||||
|
||||
response(200, 'confirmed') do
|
||||
|
@ -4,12 +4,13 @@ require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'users/registrations', type: :request do
|
||||
|
||||
path '/users' do
|
||||
path '/{slug}/users' do
|
||||
post('create registration') do
|
||||
tags 'Users Registrations'
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
|
||||
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: :body, in: :body, schema: {
|
||||
type: :object,
|
||||
required: [:user],
|
||||
|
@ -4,13 +4,14 @@ require 'swagger_helper'
|
||||
|
||||
RSpec.describe 'users/sessions', type: :request do
|
||||
|
||||
path '/users/sign_in' do
|
||||
path '/{slug}/users/sign_in' do
|
||||
|
||||
post('create session') do
|
||||
tags 'Users Sessions'
|
||||
consumes 'application/json'
|
||||
produces 'application/json'
|
||||
|
||||
parameter Swagger::Schema::SLUG
|
||||
parameter name: :body, in: :body, schema: {
|
||||
type: :object,
|
||||
required: %i[user],
|
||||
@ -35,8 +36,8 @@ RSpec.describe 'users/sessions', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
path '/users/sign_out' do
|
||||
|
||||
path '/{slug}/users/sign_out' do
|
||||
parameter Swagger::Schema::SLUG
|
||||
delete('delete session') do
|
||||
tags 'Users Sessions'
|
||||
consumes 'application/json'
|
||||
|
Loading…
x
Reference in New Issue
Block a user