From cdc6a0bda514f5e75f2c036e00b3f7d809649db0 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Tue, 3 Sep 2024 09:27:09 -0230 Subject: [PATCH 1/7] Update app to include most recent WIP changes from better_together Platform Invitations, Messaging, and Notifications --- Gemfile | 5 +- Gemfile.lock | 59 +- bin/console | 2 +- config/sidekiq.yml | 1 + ...er_platform_invitations.better_together.rb | 88 ++ ...tter_together_platforms.better_together.rb | 9 + ...3_create_noticed_tables.better_together.rb | 40 + ..._count_to_noticed_event.better_together.rb | 9 + ..._together_conversations.better_together.rb | 12 + ...etter_together_messages.better_together.rb | 13 + ...nversation_participants.better_together.rb | 12 + ..._better_together_people.better_together.rb | 9 + ...m_better_together_navigation_areas_name.rb | 9 + db/schema.rb | 1151 +++++++++-------- 14 files changed, 852 insertions(+), 567 deletions(-) create mode 100644 db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb create mode 100644 db/migrate/20240903112742_add_settings_to_better_together_platforms.better_together.rb create mode 100644 db/migrate/20240903112743_create_noticed_tables.better_together.rb create mode 100644 db/migrate/20240903112744_add_notifications_count_to_noticed_event.better_together.rb create mode 100644 db/migrate/20240903112745_create_better_together_conversations.better_together.rb create mode 100644 db/migrate/20240903112746_create_better_together_messages.better_together.rb create mode 100644 db/migrate/20240903112747_create_better_together_conversation_participants.better_together.rb create mode 100644 db/migrate/20240903112748_add_preferences_to_better_together_people.better_together.rb create mode 100644 db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb diff --git a/Gemfile b/Gemfile index 242f6a5..162d0fe 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ gem 'aws-sdk-s3', require: false # Use the published version of better_together for production gem 'better_together', '~> 0.5.0', github: 'better-together-org/community-engine-rails', - branch: 'main' + branch: 'wip/new-to-nl' # Use the local development version of better_together # gem 'better_together', '~> 0.4.1', path: '/community-engine' @@ -45,6 +45,9 @@ gem 'sentry-rails' gem 'sentry-ruby' gem 'stackprof' +# Storext for easier json attributes, custom fork for Better Together +gem 'storext', github: 'better-together-org/storext' + # Uglifier for JavaScript compression gem 'uglifier', '>= 1.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 73483d1..f125614 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GIT remote: https://github.com/better-together-org/community-engine-rails.git - revision: 490ea64c42d16ee52b9229804b18b1db5d62df02 - branch: main + revision: 7178ef418172ba2b9f7fb27ab00dcd2687ff0ebd + branch: wip/new-to-nl specs: better_together (0.5.0) activerecord-import @@ -20,7 +20,9 @@ GIT jsonapi-resources (>= 0.10.0) mobility (>= 1.0.1, < 2.0) mobility-actiontext (~> 1.1) - pundit (>= 2.1, < 2.5) + noticed + premailer-rails + pundit (>= 2.1, < 2.4) pundit-resources rack-cors (>= 1.1.1, < 2.1.0) rails (>= 5.2.2, < 7.2.0) @@ -28,6 +30,7 @@ GIT rswag (>= 2.3.1, < 2.15.0) sprockets-rails stimulus-rails (~> 1.3) + storext translate_enum turbo-rails (~> 2.0) @@ -41,6 +44,14 @@ GIT pundit rails (>= 4.2.1, < 7.2) +GIT + remote: https://github.com/better-together-org/storext.git + revision: 1d7c3707b3e412fece0022c16cc6f51564969d2c + specs: + storext (3.3.0) + activerecord (>= 4.0, < 8) + virtus + GEM remote: https://rubygems.org/ specs: @@ -149,6 +160,10 @@ GEM aws-sigv4 (~> 1.5) aws-sigv4 (1.9.1) aws-eventstream (~> 1, >= 1.0.2) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) base64 (0.2.0) bcrypt (3.1.20) better_errors (2.10.1) @@ -181,6 +196,8 @@ GEM regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) coderay (1.1.3) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) concurrent-ruby (1.3.4) connection_pool (2.4.1) coveralls (0.7.1) @@ -190,6 +207,8 @@ GEM term-ansicolor thor crass (1.0.6) + css_parser (1.19.0) + addressable dartsass-sprockets (3.1.0) railties (>= 4.0.0) sassc-embedded (~> 1.69) @@ -205,6 +224,8 @@ GEM date (3.3.4) debug_inspector (1.2.0) declarative (0.0.20) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -242,7 +263,6 @@ GEM railties (>= 5.0.0) faker (3.4.2) i18n (>= 1.8.11, < 2) - ffi (1.17.0) ffi (1.17.0-x86_64-linux-gnu) fog-aws (3.25.0) base64 (~> 0.2.0) @@ -273,12 +293,10 @@ GEM ruby-progressbar (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) - google-protobuf (4.28.0) - bigdecimal - rake (>= 13) google-protobuf (4.28.0-x86_64-linux) bigdecimal rake (>= 13) + htmlentities (4.3.4) http-accept (1.7.0) http-cookie (1.0.5) domain_name (~> 0.5) @@ -287,6 +305,7 @@ GEM i18n-timezones (1.4.8) i18n (>= 0.9.3) rails (>= 5.1.6.2) + ice_nine (0.11.2) image_processing (1.13.0) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) @@ -329,7 +348,6 @@ GEM mime-types-data (3.2024.0820) mini_magick (4.13.2) mini_mime (1.1.5) - mini_portile2 (2.8.7) minitest (5.25.1) mobility (1.2.9) i18n (>= 0.6.10, < 2) @@ -351,11 +369,10 @@ GEM net-protocol netrc (0.11.0) nio4r (2.7.3) - nokogiri (1.16.7) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) nokogiri (1.16.7-x86_64-linux) racc (~> 1.4) + noticed (2.4.1) + rails (>= 6.1.0) optimist (3.1.0) orm_adapter (0.5.0) parallel (1.26.3) @@ -364,6 +381,14 @@ GEM racc pg (1.5.7) popper_js (2.11.8) + premailer (1.27.0) + addressable + css_parser (>= 1.19.0) + htmlentities (>= 4.0.0) + premailer-rails (1.12.0) + actionmailer (>= 3) + net-smtp + premailer (~> 1.7, >= 1.7.9) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) @@ -372,7 +397,7 @@ GEM public_suffix (6.0.1) puma (6.4.2) nio4r (~> 2.0) - pundit (2.4.0) + pundit (2.3.2) activesupport (>= 3.0.0) racc (1.8.1) rack (3.1.7) @@ -521,9 +546,6 @@ GEM ffi (~> 1.12) logger rubyzip (2.3.2) - sass-embedded (1.77.8) - google-protobuf (~> 4.26) - rake (>= 13) sass-embedded (1.77.8-x86_64-linux-gnu) google-protobuf (~> 4.26) sassc (2.4.0) @@ -578,6 +600,7 @@ GEM term-ansicolor (1.8.0) tins (~> 1.0) thor (1.3.2) + thread_safe (0.3.6) tilt (2.4.0) timeout (0.4.1) tins (1.33.0) @@ -597,6 +620,10 @@ GEM execjs (>= 0.3.0, < 3) unf (0.2.0) unicode-display_width (2.5.0) + virtus (2.0.0) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) warden (1.2.9) rack (>= 2.0.9) warden-jwt_auth (0.10.0) @@ -623,7 +650,6 @@ GEM zeitwerk (2.6.18) PLATFORMS - ruby x86_64-linux DEPENDENCIES @@ -669,6 +695,7 @@ DEPENDENCIES spring spring-watcher-listen (~> 2.1.0) stackprof + storext! uglifier (>= 1.3.0) web-console (>= 3.3.0) webdrivers diff --git a/bin/console b/bin/console index 502f4a8..238e7ff 100755 --- a/bin/console +++ b/bin/console @@ -1,3 +1,3 @@ #!/usr/bin/env bash -./bin/dummy bundle exec rails c +bundle exec rails c diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 1b594dc..1faab33 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -6,6 +6,7 @@ default: &default development: <<: *default + verbose: true test: <<: *default diff --git a/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb b/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb new file mode 100644 index 0000000..1083b49 --- /dev/null +++ b/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240826143510) +# Creates the PlatformInvitations database table +class CreateBetterTogetherPlatformInvitations < ActiveRecord::Migration[7.1] + def change # rubocop:todo Metrics/AbcSize, Metrics/MethodLength + create_bt_table :platform_invitations, id: :uuid do |t| # rubocop:todo Metrics/BlockLength + # Reference to the better_together_roles table for the role + t.bt_references :community_role, + null: false, + index: { name: 'platform_invitations_by_community_role' }, + target_table: :better_together_roles + + t.string :invitee_email, + null: false, + index: { + name: 'platform_invitations_by_invitee_email' + } + + t.bt_references :invitable, + null: false, + target_table: :better_together_platforms, + index: { + name: 'platform_invitations_by_invitable' + } + + t.bt_references :invitee, + target_table: :better_together_people, + index: { + name: 'platform_invitations_by_invitee' + } + + t.bt_references :inviter, + null: false, + target_table: :better_together_people, + index: { + name: 'platform_invitations_by_inviter' + } + + # Reference to the better_together_roles table for the role + t.bt_references :platform_role, + null: true, + index: { name: 'platform_invitations_by_platform_role' }, + target_table: :better_together_roles + + t.string :status, + limit: 20, + null: false, + index: { + name: 'platform_invitations_by_status' + } + + t.string :locale, + limit: 5, + null: false, + index: { + name: 'platform_invitations_by_locale' + }, + default: I18n.default_locale + + t.string :token, + limit: 24, + null: false, + index: { + name: 'platform_invitations_by_token', + unique: true + } + + t.datetime :valid_from, + null: false, + index: { + name: 'platform_invitations_by_valid_from' + } + t.datetime :valid_until, + index: { + name: 'platform_invitations_by_valid_until' + } + t.datetime :last_sent + t.datetime :accepted_at + end + + add_index :better_together_platform_invitations, %i[invitee_email invitable_id], unique: true + add_index :better_together_platform_invitations, %i[invitable_id status], + name: "index_platform_invitations_on_invitable_id_and_status" + add_index :better_together_platform_invitations, :invitee_email, where: "status = 'pending'", + name: "index_pending_invitations_on_invitee_email" + end +end diff --git a/db/migrate/20240903112742_add_settings_to_better_together_platforms.better_together.rb b/db/migrate/20240903112742_add_settings_to_better_together_platforms.better_together.rb new file mode 100644 index 0000000..e41d85c --- /dev/null +++ b/db/migrate/20240903112742_add_settings_to_better_together_platforms.better_together.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240831140605) +# Adds a jsonb column to platforms to allow for dynmaic and flexible storage and retrieval of settings +class AddSettingsToBetterTogetherPlatforms < ActiveRecord::Migration[7.1] + def change + add_column :better_together_platforms, :settings, :jsonb, null: false, default: {} + end +end diff --git a/db/migrate/20240903112743_create_noticed_tables.better_together.rb b/db/migrate/20240903112743_create_noticed_tables.better_together.rb new file mode 100644 index 0000000..0bc4cac --- /dev/null +++ b/db/migrate/20240903112743_create_noticed_tables.better_together.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240901173824) +# This migration comes from noticed (originally 20231215190233) +class CreateNoticedTables < ActiveRecord::Migration[6.1] + def change # rubocop:todo Metrics/MethodLength + primary_key_type, foreign_key_type = primary_and_foreign_key_types + create_table :noticed_events, id: primary_key_type do |t| + t.string :type + t.belongs_to :record, polymorphic: true, type: foreign_key_type + if t.respond_to?(:jsonb) + t.jsonb :params + else + t.json :params + end + + t.timestamps + end + + create_table :noticed_notifications, id: primary_key_type do |t| + t.string :type + t.belongs_to :event, null: false, type: foreign_key_type + t.belongs_to :recipient, polymorphic: true, null: false, type: foreign_key_type + t.datetime :read_at + t.datetime :seen_at + + t.timestamps + end + end + + private + + def primary_and_foreign_key_types + config = Rails.configuration.generators + setting = config.options[config.orm][:primary_key_type] + primary_key_type = setting || :primary_key + foreign_key_type = setting || :bigint + [primary_key_type, foreign_key_type] + end +end diff --git a/db/migrate/20240903112744_add_notifications_count_to_noticed_event.better_together.rb b/db/migrate/20240903112744_add_notifications_count_to_noticed_event.better_together.rb new file mode 100644 index 0000000..7535ffb --- /dev/null +++ b/db/migrate/20240903112744_add_notifications_count_to_noticed_event.better_together.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240901173825) +# This migration comes from noticed (originally 20240129184740) +class AddNotificationsCountToNoticedEvent < ActiveRecord::Migration[6.1] + def change + add_column :noticed_events, :notifications_count, :integer + end +end diff --git a/db/migrate/20240903112745_create_better_together_conversations.better_together.rb b/db/migrate/20240903112745_create_better_together_conversations.better_together.rb new file mode 100644 index 0000000..b67b43b --- /dev/null +++ b/db/migrate/20240903112745_create_better_together_conversations.better_together.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240901182643) +# Creates the conversations table used to group conversations for participants +class CreateBetterTogetherConversations < ActiveRecord::Migration[7.1] + def change + create_bt_table :conversations do |t| + t.string :title, null: false + t.bt_references :creator, target_table: :better_together_people, null: false + end + end +end diff --git a/db/migrate/20240903112746_create_better_together_messages.better_together.rb b/db/migrate/20240903112746_create_better_together_messages.better_together.rb new file mode 100644 index 0000000..a00d177 --- /dev/null +++ b/db/migrate/20240903112746_create_better_together_messages.better_together.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240901182909) +# Creates the messages table used to communicate between people +class CreateBetterTogetherMessages < ActiveRecord::Migration[7.1] + def change + create_bt_table :messages do |t| + t.text :content, null: false + t.bt_references :sender, null: false, target_table: :better_together_people + t.bt_references :conversation, null: false + end + end +end diff --git a/db/migrate/20240903112747_create_better_together_conversation_participants.better_together.rb b/db/migrate/20240903112747_create_better_together_conversation_participants.better_together.rb new file mode 100644 index 0000000..21eb37c --- /dev/null +++ b/db/migrate/20240903112747_create_better_together_conversation_participants.better_together.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240901193934) +# Creates a join table to link people to conversations as participants +class CreateBetterTogetherConversationParticipants < ActiveRecord::Migration[7.1] + def change + create_bt_table :conversation_participants do |t| + t.bt_references :conversation, null: false + t.bt_references :person, null: false + end + end +end diff --git a/db/migrate/20240903112748_add_preferences_to_better_together_people.better_together.rb b/db/migrate/20240903112748_add_preferences_to_better_together_people.better_together.rb new file mode 100644 index 0000000..003f95c --- /dev/null +++ b/db/migrate/20240903112748_add_preferences_to_better_together_people.better_together.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240902153051) +# Adds a preferences jsonb column to track and store dynamic attributes like locale and time zone +class AddPreferencesToBetterTogetherPeople < ActiveRecord::Migration[7.1] + def change + add_column :better_together_people, :preferences, :jsonb, null: false, default: {} + end +end diff --git a/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb b/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb new file mode 100644 index 0000000..1186986 --- /dev/null +++ b/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb @@ -0,0 +1,9 @@ +class RemoveColumnNullConstraintFromBetterTogetherNavigationAreasName < ActiveRecord::Migration[7.1] + def up + change_column_null :better_together_navigation_areas, :name, true + end + + def down + change_column_null :better_together_navigation_areas, :name, false + end +end diff --git a/db/schema.rb b/db/schema.rb index 98f74ab..12cd4f6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -12,552 +10,607 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 20_240_812_151_058) do # rubocop:todo Metrics/BlockLength +ActiveRecord::Schema[7.1].define(version: 2024_09_03_114604) do # These are extensions that must be enabled in order to support this database - enable_extension 'pgcrypto' - enable_extension 'plpgsql' - enable_extension 'postgis' - - create_table 'action_text_rich_texts', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.string 'name', null: false - t.text 'body' - t.string 'record_type', null: false - t.uuid 'record_id', null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'locale', null: false - t.index %w[record_type record_id name locale], name: 'index_action_text_rich_texts_uniqueness', - unique: true - end - - create_table 'active_storage_attachments', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.string 'name', null: false - t.string 'record_type', null: false - t.uuid 'record_id', null: false - t.uuid 'blob_id', null: false - t.datetime 'created_at', null: false - t.index ['blob_id'], name: 'index_active_storage_attachments_on_blob_id' - t.index %w[record_type record_id name blob_id], name: 'index_active_storage_attachments_uniqueness', - unique: true - end - - create_table 'active_storage_blobs', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.string 'key', null: false - t.string 'filename', null: false - t.string 'content_type' - t.text 'metadata' - t.string 'service_name', null: false - t.bigint 'byte_size', null: false - t.string 'checksum' - t.datetime 'created_at', null: false - t.index ['key'], name: 'index_active_storage_blobs_on_key', unique: true - end - - create_table 'active_storage_variant_records', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.uuid 'blob_id', null: false - t.string 'variation_digest', null: false - t.index %w[blob_id variation_digest], name: 'index_active_storage_variant_records_uniqueness', unique: true - end - - create_table 'better_together_communities', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'host', default: false, null: false - t.boolean 'protected', default: false, null: false - t.string 'privacy', limit: 50, default: 'public', null: false - t.string 'slug', null: false - t.uuid 'creator_id' - t.index ['creator_id'], name: 'by_creator' - t.index ['host'], name: 'index_better_together_communities_on_host', unique: true, where: '(host IS TRUE)' - t.index ['identifier'], name: 'index_better_together_communities_on_identifier', unique: true - t.index ['privacy'], name: 'by_community_privacy' - t.index ['slug'], name: 'index_better_together_communities_on_slug', unique: true - end - - create_table 'better_together_geography_continents', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.uuid 'community_id', null: false - t.string 'slug', null: false - t.index ['community_id'], name: 'by_geography_continent_community' - t.index ['identifier'], name: 'index_better_together_geography_continents_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_geography_continents_on_slug', unique: true - end - - create_table 'better_together_geography_countries', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.string 'iso_code', limit: 2, null: false - t.boolean 'protected', default: false, null: false - t.uuid 'community_id', null: false - t.string 'slug', null: false - t.index ['community_id'], name: 'by_geography_country_community' - t.index ['identifier'], name: 'index_better_together_geography_countries_on_identifier', unique: true - t.index ['iso_code'], name: 'index_better_together_geography_countries_on_iso_code', unique: true - t.index ['slug'], name: 'index_better_together_geography_countries_on_slug', unique: true - end - - create_table 'better_together_geography_country_continents', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.uuid 'country_id' - t.uuid 'continent_id' - t.index ['continent_id'], name: 'country_continent_by_continent' - t.index %w[country_id continent_id], name: 'index_country_continents_on_country_and_continent', unique: true - t.index ['country_id'], name: 'country_continent_by_country' - end - - create_table 'better_together_geography_region_settlements', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.boolean 'protected', default: false, null: false - t.uuid 'region_id' - t.uuid 'settlement_id' - t.index ['region_id'], name: 'bt_region_settlement_by_region' - t.index ['settlement_id'], name: 'bt_region_settlement_by_settlement' - end - - create_table 'better_together_geography_regions', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.uuid 'community_id', null: false - t.uuid 'country_id' - t.uuid 'state_id' - t.string 'slug', null: false - t.string 'type', default: 'BetterTogether::Geography::Region', null: false - t.index ['community_id'], name: 'by_geography_region_community' - t.index ['country_id'], name: 'index_better_together_geography_regions_on_country_id' - t.index ['identifier'], name: 'index_better_together_geography_regions_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_geography_regions_on_slug', unique: true - t.index ['state_id'], name: 'index_better_together_geography_regions_on_state_id' - end - - create_table 'better_together_geography_settlements', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.uuid 'community_id', null: false - t.uuid 'country_id' - t.uuid 'state_id' - t.string 'slug', null: false - t.index ['community_id'], name: 'by_geography_settlement_community' - t.index ['country_id'], name: 'index_better_together_geography_settlements_on_country_id' - t.index ['identifier'], name: 'index_better_together_geography_settlements_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_geography_settlements_on_slug', unique: true - t.index ['state_id'], name: 'index_better_together_geography_settlements_on_state_id' - end - - create_table 'better_together_geography_states', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.string 'iso_code', limit: 5, null: false - t.boolean 'protected', default: false, null: false - t.uuid 'community_id', null: false - t.uuid 'country_id' - t.string 'slug', null: false - t.index ['community_id'], name: 'by_geography_state_community' - t.index ['country_id'], name: 'index_better_together_geography_states_on_country_id' - t.index ['identifier'], name: 'index_better_together_geography_states_on_identifier', unique: true - t.index ['iso_code'], name: 'index_better_together_geography_states_on_iso_code', unique: true - t.index ['slug'], name: 'index_better_together_geography_states_on_slug', unique: true - end - - create_table 'better_together_identifications', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.boolean 'active', null: false - t.string 'identity_type', null: false - t.uuid 'identity_id', null: false - t.string 'agent_type', null: false - t.uuid 'agent_id', null: false - t.index %w[active agent_type agent_id], name: 'active_identification', unique: true - t.index ['active'], name: 'by_active_state' - t.index %w[agent_type agent_id], name: 'by_agent' - t.index %w[identity_type identity_id agent_type agent_id], name: 'unique_identification', unique: true - t.index %w[identity_type identity_id], name: 'by_identity' - end - - create_table 'better_together_jwt_denylists', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'jti' - t.datetime 'exp' - t.index ['jti'], name: 'index_better_together_jwt_denylists_on_jti' - end - - create_table 'better_together_navigation_areas', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.string 'slug', null: false - t.boolean 'visible', default: true, null: false - t.string 'name', null: false - t.string 'style' - t.string 'navigable_type' - t.bigint 'navigable_id' - t.index ['identifier'], name: 'index_better_together_navigation_areas_on_identifier', unique: true - t.index %w[navigable_type navigable_id], name: 'by_navigable' - t.index ['slug'], name: 'index_better_together_navigation_areas_on_slug', unique: true - end - - create_table 'better_together_navigation_items', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.integer 'position', null: false - t.boolean 'protected', default: false, null: false - t.string 'slug', null: false - t.boolean 'visible', default: true, null: false - t.uuid 'navigation_area_id', null: false - t.uuid 'parent_id' - t.string 'url' - t.string 'icon' - t.string 'item_type', null: false - t.string 'linkable_type' - t.uuid 'linkable_id' - t.index ['identifier'], name: 'index_better_together_navigation_items_on_identifier', unique: true - t.index %w[linkable_type linkable_id], name: 'by_linkable' - t.index %w[navigation_area_id parent_id position], name: 'navigation_items_area_position', unique: true - t.index ['navigation_area_id'], name: 'index_better_together_navigation_items_on_navigation_area_id' - t.index ['parent_id'], name: 'by_nav_item_parent' - t.index ['slug'], name: 'index_better_together_navigation_items_on_slug', unique: true - end - - create_table 'better_together_pages', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.string 'slug', null: false - t.text 'meta_description' - t.string 'keywords' - t.boolean 'published' - t.datetime 'published_at' - t.string 'privacy', default: 'public', null: false - t.string 'layout' - t.string 'template' - t.string 'language', default: 'en' - t.index ['identifier'], name: 'index_better_together_pages_on_identifier', unique: true - t.index ['privacy'], name: 'by_page_privacy' - t.index ['published'], name: 'by_page_publication_status' - t.index ['published_at'], name: 'by_page_publication_date' - t.index ['slug'], name: 'index_better_together_pages_on_slug', unique: true - end - - create_table 'better_together_people', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.string 'slug', null: false - t.uuid 'community_id', null: false - t.index ['community_id'], name: 'by_person_community' - t.index ['identifier'], name: 'index_better_together_people_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_people_on_slug', unique: true - end - - create_table 'better_together_person_community_memberships', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.uuid 'member_id', null: false - t.uuid 'joinable_id', null: false - t.uuid 'role_id', null: false - t.index %w[joinable_id member_id role_id], name: 'unique_person_community_membership_member_role', - unique: true - t.index ['joinable_id'], name: 'person_community_membership_by_joinable' - t.index ['member_id'], name: 'person_community_membership_by_member' - t.index ['role_id'], name: 'person_community_membership_by_role' - end - - create_table 'better_together_person_platform_memberships', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.uuid 'member_id', null: false - t.uuid 'joinable_id', null: false - t.uuid 'role_id', null: false - t.index %w[joinable_id member_id role_id], name: 'unique_person_platform_membership_member_role', unique: true - t.index ['joinable_id'], name: 'person_platform_membership_by_joinable' - t.index ['member_id'], name: 'person_platform_membership_by_member' - t.index ['role_id'], name: 'person_platform_membership_by_role' - end - - create_table 'better_together_platforms', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'host', default: false, null: false - t.boolean 'protected', default: false, null: false - t.string 'privacy', limit: 50, default: 'public', null: false - t.string 'slug', null: false - t.uuid 'community_id' - t.string 'url', null: false - t.string 'time_zone', null: false - t.index ['community_id'], name: 'by_platform_community' - t.index ['host'], name: 'index_better_together_platforms_on_host', unique: true, where: '(host IS TRUE)' - t.index ['identifier'], name: 'index_better_together_platforms_on_identifier', unique: true - t.index ['privacy'], name: 'by_platform_privacy' - t.index ['slug'], name: 'index_better_together_platforms_on_slug', unique: true - t.index ['url'], name: 'index_better_together_platforms_on_url', unique: true - end - - create_table 'better_together_resource_permissions', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.integer 'position', null: false - t.string 'resource_type', null: false - t.string 'slug', null: false - t.string 'action', null: false - t.string 'target', null: false - t.index ['identifier'], name: 'index_better_together_resource_permissions_on_identifier', unique: true - t.index %w[resource_type position], name: 'index_resource_permissions_on_resource_type_and_position', - unique: true - t.index ['slug'], name: 'index_better_together_resource_permissions_on_slug', unique: true - end - - create_table 'better_together_role_resource_permissions', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.uuid 'role_id', null: false - t.uuid 'resource_permission_id', null: false - t.index ['resource_permission_id'], name: 'role_resource_permissions_resource_permission' - t.index %w[role_id resource_permission_id], name: 'unique_role_resource_permission_index', unique: true - t.index ['role_id'], name: 'role_resource_permissions_role' - end - - create_table 'better_together_roles', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.integer 'position', null: false - t.string 'resource_type', null: false - t.string 'slug', null: false - t.index ['identifier'], name: 'index_better_together_roles_on_identifier', unique: true - t.index %w[resource_type position], name: 'index_roles_on_resource_type_and_position', unique: true - t.index ['slug'], name: 'index_better_together_roles_on_slug', unique: true - end - - create_table 'better_together_users', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'email', default: '', null: false - t.string 'encrypted_password', default: '', null: false - t.string 'reset_password_token' - t.datetime 'reset_password_sent_at' - t.datetime 'remember_created_at' - t.integer 'sign_in_count', default: 0, null: false - t.datetime 'current_sign_in_at' - t.datetime 'last_sign_in_at' - t.string 'current_sign_in_ip' - t.string 'last_sign_in_ip' - t.string 'confirmation_token' - t.datetime 'confirmed_at' - t.datetime 'confirmation_sent_at' - t.string 'unconfirmed_email' - t.integer 'failed_attempts', default: 0, null: false - t.string 'unlock_token' - t.datetime 'locked_at' - t.index ['confirmation_token'], name: 'index_better_together_users_on_confirmation_token', unique: true - t.index ['email'], name: 'index_better_together_users_on_email', unique: true - t.index ['reset_password_token'], name: 'index_better_together_users_on_reset_password_token', unique: true - t.index ['unlock_token'], name: 'index_better_together_users_on_unlock_token', unique: true - end - - create_table 'better_together_wizard_step_definitions', id: :uuid, default: lambda { - 'gen_random_uuid()' - }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.string 'slug', null: false - t.uuid 'wizard_id', null: false - t.string 'template' - t.string 'form_class' - t.string 'message', default: 'Please complete this next step.', null: false - t.integer 'step_number', null: false - t.index ['identifier'], name: 'index_better_together_wizard_step_definitions_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_wizard_step_definitions_on_slug', unique: true - t.index %w[wizard_id step_number], name: 'index_wizard_step_definitions_on_wizard_id_and_step_number', - unique: true - t.index ['wizard_id'], name: 'by_step_definition_wizard' - end - - create_table 'better_together_wizard_steps', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.uuid 'wizard_id', null: false - t.uuid 'wizard_step_definition_id', null: false - t.uuid 'creator_id' - t.string 'identifier', limit: 100, null: false - t.boolean 'completed', default: false - t.integer 'step_number', null: false - t.index ['creator_id'], name: 'by_step_creator' - t.index ['identifier'], name: 'by_step_identifier' - t.index %w[wizard_id identifier creator_id], name: 'index_unique_wizard_steps', unique: true, - where: '(completed IS FALSE)' - t.index %w[wizard_id step_number], name: 'index_wizard_steps_on_wizard_id_and_step_number' - t.index ['wizard_id'], name: 'by_step_wizard' - t.index ['wizard_step_definition_id'], name: 'by_step_wizard_step_definition' - end - - create_table 'better_together_wizards', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'identifier', limit: 100, null: false - t.boolean 'protected', default: false, null: false - t.string 'slug', null: false - t.integer 'max_completions', default: 0, null: false - t.integer 'current_completions', default: 0, null: false - t.datetime 'first_completed_at' - t.datetime 'last_completed_at' - t.text 'success_message', default: 'Thank you. You have successfully completed the wizard', null: false - t.string 'success_path', default: '/', null: false - t.index ['identifier'], name: 'index_better_together_wizards_on_identifier', unique: true - t.index ['slug'], name: 'index_better_together_wizards_on_slug', unique: true - end - - create_table 'friendly_id_slugs', force: :cascade do |t| - t.string 'slug', null: false - t.uuid 'sluggable_id', null: false - t.string 'sluggable_type', null: false - t.string 'scope' - t.integer 'lock_version', default: 0, null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'locale', null: false - t.index ['locale'], name: 'index_friendly_id_slugs_on_locale' - t.index %w[slug sluggable_type locale], name: 'index_friendly_id_slugs_on_slug_and_sluggable_type_and_locale' - t.index %w[slug sluggable_type scope locale], name: 'index_friendly_id_slugs_unique', unique: true - t.index %w[sluggable_type sluggable_id], name: 'by_sluggable' - end - - create_table 'mobility_string_translations', force: :cascade do |t| - t.string 'locale', null: false - t.string 'key', null: false - t.string 'value' - t.string 'translatable_type' - t.uuid 'translatable_id' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index %w[translatable_id translatable_type key], - name: 'index_mobility_string_translations_on_translatable_attribute' - t.index %w[translatable_id translatable_type locale key], - name: 'index_mobility_string_translations_on_keys', unique: true - t.index %w[translatable_type key value locale], name: 'index_mobility_string_translations_on_query_keys' - end - - create_table 'mobility_text_translations', force: :cascade do |t| - t.string 'locale', null: false - t.string 'key', null: false - t.text 'value' - t.string 'translatable_type' - t.uuid 'translatable_id' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index %w[translatable_id translatable_type key], - name: 'index_mobility_text_translations_on_translatable_attribute' - t.index %w[translatable_id translatable_type locale key], - name: 'index_mobility_text_translations_on_keys', unique: true - end - - add_foreign_key 'active_storage_attachments', 'active_storage_blobs', column: 'blob_id' - add_foreign_key 'active_storage_variant_records', 'active_storage_blobs', column: 'blob_id' - add_foreign_key 'better_together_communities', 'better_together_people', column: 'creator_id' - add_foreign_key 'better_together_geography_continents', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_geography_countries', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_geography_country_continents', 'better_together_geography_continents', - column: 'continent_id' - add_foreign_key 'better_together_geography_country_continents', 'better_together_geography_countries', - column: 'country_id' - add_foreign_key 'better_together_geography_region_settlements', 'better_together_geography_regions', - column: 'region_id' - add_foreign_key 'better_together_geography_region_settlements', 'better_together_geography_settlements', - column: 'settlement_id' - add_foreign_key 'better_together_geography_regions', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_geography_regions', 'better_together_geography_countries', column: 'country_id' - add_foreign_key 'better_together_geography_regions', 'better_together_geography_states', column: 'state_id' - add_foreign_key 'better_together_geography_settlements', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_geography_settlements', 'better_together_geography_countries', column: 'country_id' - add_foreign_key 'better_together_geography_settlements', 'better_together_geography_states', column: 'state_id' - add_foreign_key 'better_together_geography_states', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_geography_states', 'better_together_geography_countries', column: 'country_id' - add_foreign_key 'better_together_navigation_items', 'better_together_navigation_areas', column: 'navigation_area_id' - add_foreign_key 'better_together_navigation_items', 'better_together_navigation_items', column: 'parent_id' - add_foreign_key 'better_together_people', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_person_community_memberships', 'better_together_communities', column: 'joinable_id' - add_foreign_key 'better_together_person_community_memberships', 'better_together_people', column: 'member_id' - add_foreign_key 'better_together_person_community_memberships', 'better_together_roles', column: 'role_id' - add_foreign_key 'better_together_person_platform_memberships', 'better_together_people', column: 'member_id' - add_foreign_key 'better_together_person_platform_memberships', 'better_together_platforms', column: 'joinable_id' - add_foreign_key 'better_together_person_platform_memberships', 'better_together_roles', column: 'role_id' - add_foreign_key 'better_together_platforms', 'better_together_communities', column: 'community_id' - add_foreign_key 'better_together_role_resource_permissions', 'better_together_resource_permissions', - column: 'resource_permission_id' - add_foreign_key 'better_together_role_resource_permissions', 'better_together_roles', column: 'role_id' - add_foreign_key 'better_together_wizard_step_definitions', 'better_together_wizards', column: 'wizard_id' - add_foreign_key 'better_together_wizard_steps', 'better_together_people', column: 'creator_id' - add_foreign_key 'better_together_wizard_steps', 'better_together_wizard_step_definitions', - column: 'wizard_step_definition_id' - add_foreign_key 'better_together_wizard_steps', 'better_together_wizards', column: 'wizard_id' + enable_extension "pgcrypto" + enable_extension "plpgsql" + enable_extension "postgis" + + create_table "action_text_rich_texts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name", null: false + t.text "body" + t.string "record_type", null: false + t.uuid "record_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "locale", null: false + t.index ["record_type", "record_id", "name", "locale"], name: "index_action_text_rich_texts_uniqueness", unique: true + end + + create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.uuid "record_id", null: false + t.uuid "blob_id", null: false + t.datetime "created_at", null: false + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true + end + + create_table "active_storage_blobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "key", null: false + t.string "filename", null: false + t.string "content_type" + t.text "metadata" + t.string "service_name", null: false + t.bigint "byte_size", null: false + t.string "checksum" + t.datetime "created_at", null: false + t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true + end + + create_table "active_storage_variant_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "blob_id", null: false + t.string "variation_digest", null: false + t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true + end + + create_table "better_together_communities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "host", default: false, null: false + t.boolean "protected", default: false, null: false + t.string "privacy", limit: 50, default: "public", null: false + t.string "slug", null: false + t.uuid "creator_id" + t.index ["creator_id"], name: "by_creator" + t.index ["host"], name: "index_better_together_communities_on_host", unique: true, where: "(host IS TRUE)" + t.index ["identifier"], name: "index_better_together_communities_on_identifier", unique: true + t.index ["privacy"], name: "by_community_privacy" + t.index ["slug"], name: "index_better_together_communities_on_slug", unique: true + end + + create_table "better_together_conversation_participants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "conversation_id", null: false + t.uuid "person_id", null: false + t.index ["conversation_id"], name: "idx_on_conversation_id_30b3b70bad" + t.index ["person_id"], name: "index_better_together_conversation_participants_on_person_id" + end + + create_table "better_together_conversations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "title", null: false + t.uuid "creator_id", null: false + t.index ["creator_id"], name: "index_better_together_conversations_on_creator_id" + end + + create_table "better_together_geography_continents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.uuid "community_id", null: false + t.string "slug", null: false + t.index ["community_id"], name: "by_geography_continent_community" + t.index ["identifier"], name: "index_better_together_geography_continents_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_geography_continents_on_slug", unique: true + end + + create_table "better_together_geography_countries", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.string "iso_code", limit: 2, null: false + t.boolean "protected", default: false, null: false + t.uuid "community_id", null: false + t.string "slug", null: false + t.index ["community_id"], name: "by_geography_country_community" + t.index ["identifier"], name: "index_better_together_geography_countries_on_identifier", unique: true + t.index ["iso_code"], name: "index_better_together_geography_countries_on_iso_code", unique: true + t.index ["slug"], name: "index_better_together_geography_countries_on_slug", unique: true + end + + create_table "better_together_geography_country_continents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "country_id" + t.uuid "continent_id" + t.index ["continent_id"], name: "country_continent_by_continent" + t.index ["country_id", "continent_id"], name: "index_country_continents_on_country_and_continent", unique: true + t.index ["country_id"], name: "country_continent_by_country" + end + + create_table "better_together_geography_region_settlements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "protected", default: false, null: false + t.uuid "region_id" + t.uuid "settlement_id" + t.index ["region_id"], name: "bt_region_settlement_by_region" + t.index ["settlement_id"], name: "bt_region_settlement_by_settlement" + end + + create_table "better_together_geography_regions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.uuid "community_id", null: false + t.uuid "country_id" + t.uuid "state_id" + t.string "slug", null: false + t.string "type", default: "BetterTogether::Geography::Region", null: false + t.index ["community_id"], name: "by_geography_region_community" + t.index ["country_id"], name: "index_better_together_geography_regions_on_country_id" + t.index ["identifier"], name: "index_better_together_geography_regions_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_geography_regions_on_slug", unique: true + t.index ["state_id"], name: "index_better_together_geography_regions_on_state_id" + end + + create_table "better_together_geography_settlements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.uuid "community_id", null: false + t.uuid "country_id" + t.uuid "state_id" + t.string "slug", null: false + t.index ["community_id"], name: "by_geography_settlement_community" + t.index ["country_id"], name: "index_better_together_geography_settlements_on_country_id" + t.index ["identifier"], name: "index_better_together_geography_settlements_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_geography_settlements_on_slug", unique: true + t.index ["state_id"], name: "index_better_together_geography_settlements_on_state_id" + end + + create_table "better_together_geography_states", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.string "iso_code", limit: 5, null: false + t.boolean "protected", default: false, null: false + t.uuid "community_id", null: false + t.uuid "country_id" + t.string "slug", null: false + t.index ["community_id"], name: "by_geography_state_community" + t.index ["country_id"], name: "index_better_together_geography_states_on_country_id" + t.index ["identifier"], name: "index_better_together_geography_states_on_identifier", unique: true + t.index ["iso_code"], name: "index_better_together_geography_states_on_iso_code", unique: true + t.index ["slug"], name: "index_better_together_geography_states_on_slug", unique: true + end + + create_table "better_together_identifications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "active", null: false + t.string "identity_type", null: false + t.uuid "identity_id", null: false + t.string "agent_type", null: false + t.uuid "agent_id", null: false + t.index ["active", "agent_type", "agent_id"], name: "active_identification", unique: true + t.index ["active"], name: "by_active_state" + t.index ["agent_type", "agent_id"], name: "by_agent" + t.index ["identity_type", "identity_id", "agent_type", "agent_id"], name: "unique_identification", unique: true + t.index ["identity_type", "identity_id"], name: "by_identity" + end + + create_table "better_together_jwt_denylists", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "jti" + t.datetime "exp" + t.index ["jti"], name: "index_better_together_jwt_denylists_on_jti" + end + + create_table "better_together_messages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.text "content", null: false + t.uuid "sender_id", null: false + t.uuid "conversation_id", null: false + t.index ["conversation_id"], name: "index_better_together_messages_on_conversation_id" + t.index ["sender_id"], name: "index_better_together_messages_on_sender_id" + end + + create_table "better_together_navigation_areas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.string "slug", null: false + t.boolean "visible", default: true, null: false + t.string "name" + t.string "style" + t.string "navigable_type" + t.bigint "navigable_id" + t.index ["identifier"], name: "index_better_together_navigation_areas_on_identifier", unique: true + t.index ["navigable_type", "navigable_id"], name: "by_navigable" + t.index ["slug"], name: "index_better_together_navigation_areas_on_slug", unique: true + end + + create_table "better_together_navigation_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.integer "position", null: false + t.boolean "protected", default: false, null: false + t.string "slug", null: false + t.boolean "visible", default: true, null: false + t.uuid "navigation_area_id", null: false + t.uuid "parent_id" + t.string "url" + t.string "icon" + t.string "item_type", null: false + t.string "linkable_type" + t.uuid "linkable_id" + t.index ["identifier"], name: "index_better_together_navigation_items_on_identifier", unique: true + t.index ["linkable_type", "linkable_id"], name: "by_linkable" + t.index ["navigation_area_id", "parent_id", "position"], name: "navigation_items_area_position", unique: true + t.index ["navigation_area_id"], name: "index_better_together_navigation_items_on_navigation_area_id" + t.index ["parent_id"], name: "by_nav_item_parent" + t.index ["slug"], name: "index_better_together_navigation_items_on_slug", unique: true + end + + create_table "better_together_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.string "slug", null: false + t.text "meta_description" + t.string "keywords" + t.boolean "published" + t.datetime "published_at" + t.string "privacy", default: "public", null: false + t.string "layout" + t.string "template" + t.string "language", default: "en" + t.index ["identifier"], name: "index_better_together_pages_on_identifier", unique: true + t.index ["privacy"], name: "by_page_privacy" + t.index ["published"], name: "by_page_publication_status" + t.index ["published_at"], name: "by_page_publication_date" + t.index ["slug"], name: "index_better_together_pages_on_slug", unique: true + end + + create_table "better_together_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.string "slug", null: false + t.uuid "community_id", null: false + t.jsonb "preferences", default: {}, null: false + t.index ["community_id"], name: "by_person_community" + t.index ["identifier"], name: "index_better_together_people_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_people_on_slug", unique: true + end + + create_table "better_together_person_community_memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "member_id", null: false + t.uuid "joinable_id", null: false + t.uuid "role_id", null: false + t.index ["joinable_id", "member_id", "role_id"], name: "unique_person_community_membership_member_role", unique: true + t.index ["joinable_id"], name: "person_community_membership_by_joinable" + t.index ["member_id"], name: "person_community_membership_by_member" + t.index ["role_id"], name: "person_community_membership_by_role" + end + + create_table "better_together_person_platform_memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "member_id", null: false + t.uuid "joinable_id", null: false + t.uuid "role_id", null: false + t.index ["joinable_id", "member_id", "role_id"], name: "unique_person_platform_membership_member_role", unique: true + t.index ["joinable_id"], name: "person_platform_membership_by_joinable" + t.index ["member_id"], name: "person_platform_membership_by_member" + t.index ["role_id"], name: "person_platform_membership_by_role" + end + + create_table "better_together_platform_invitations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "community_role_id", null: false + t.string "invitee_email", null: false + t.uuid "invitable_id", null: false + t.uuid "invitee_id" + t.uuid "inviter_id", null: false + t.uuid "platform_role_id" + t.string "status", limit: 20, null: false + t.string "locale", limit: 5, default: "en", null: false + t.string "token", limit: 24, null: false + t.datetime "valid_from", null: false + t.datetime "valid_until" + t.datetime "last_sent" + t.datetime "accepted_at" + t.index ["community_role_id"], name: "platform_invitations_by_community_role" + t.index ["invitable_id", "status"], name: "index_platform_invitations_on_invitable_id_and_status" + t.index ["invitable_id"], name: "platform_invitations_by_invitable" + t.index ["invitee_email", "invitable_id"], name: "idx_on_invitee_email_invitable_id_5a7d642388", unique: true + t.index ["invitee_email"], name: "index_pending_invitations_on_invitee_email", where: "((status)::text = 'pending'::text)" + t.index ["invitee_email"], name: "platform_invitations_by_invitee_email" + t.index ["invitee_id"], name: "platform_invitations_by_invitee" + t.index ["inviter_id"], name: "platform_invitations_by_inviter" + t.index ["locale"], name: "platform_invitations_by_locale" + t.index ["platform_role_id"], name: "platform_invitations_by_platform_role" + t.index ["status"], name: "platform_invitations_by_status" + t.index ["token"], name: "platform_invitations_by_token", unique: true + t.index ["valid_from"], name: "platform_invitations_by_valid_from" + t.index ["valid_until"], name: "platform_invitations_by_valid_until" + end + + create_table "better_together_platforms", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "host", default: false, null: false + t.boolean "protected", default: false, null: false + t.string "privacy", limit: 50, default: "public", null: false + t.string "slug", null: false + t.uuid "community_id" + t.string "url", null: false + t.string "time_zone", null: false + t.jsonb "settings", default: {}, null: false + t.index ["community_id"], name: "by_platform_community" + t.index ["host"], name: "index_better_together_platforms_on_host", unique: true, where: "(host IS TRUE)" + t.index ["identifier"], name: "index_better_together_platforms_on_identifier", unique: true + t.index ["privacy"], name: "by_platform_privacy" + t.index ["slug"], name: "index_better_together_platforms_on_slug", unique: true + t.index ["url"], name: "index_better_together_platforms_on_url", unique: true + end + + create_table "better_together_resource_permissions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.integer "position", null: false + t.string "resource_type", null: false + t.string "slug", null: false + t.string "action", null: false + t.string "target", null: false + t.index ["identifier"], name: "index_better_together_resource_permissions_on_identifier", unique: true + t.index ["resource_type", "position"], name: "index_resource_permissions_on_resource_type_and_position", unique: true + t.index ["slug"], name: "index_better_together_resource_permissions_on_slug", unique: true + end + + create_table "better_together_role_resource_permissions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "role_id", null: false + t.uuid "resource_permission_id", null: false + t.index ["resource_permission_id"], name: "role_resource_permissions_resource_permission" + t.index ["role_id", "resource_permission_id"], name: "unique_role_resource_permission_index", unique: true + t.index ["role_id"], name: "role_resource_permissions_role" + end + + create_table "better_together_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.integer "position", null: false + t.string "resource_type", null: false + t.string "slug", null: false + t.index ["identifier"], name: "index_better_together_roles_on_identifier", unique: true + t.index ["resource_type", "position"], name: "index_roles_on_resource_type_and_position", unique: true + t.index ["slug"], name: "index_better_together_roles_on_slug", unique: true + end + + create_table "better_together_users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.integer "sign_in_count", default: 0, null: false + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "confirmation_sent_at" + t.string "unconfirmed_email" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" + t.datetime "locked_at" + t.index ["confirmation_token"], name: "index_better_together_users_on_confirmation_token", unique: true + t.index ["email"], name: "index_better_together_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_better_together_users_on_reset_password_token", unique: true + t.index ["unlock_token"], name: "index_better_together_users_on_unlock_token", unique: true + end + + create_table "better_together_wizard_step_definitions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.string "slug", null: false + t.uuid "wizard_id", null: false + t.string "template" + t.string "form_class" + t.string "message", default: "Please complete this next step.", null: false + t.integer "step_number", null: false + t.index ["identifier"], name: "index_better_together_wizard_step_definitions_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_wizard_step_definitions_on_slug", unique: true + t.index ["wizard_id", "step_number"], name: "index_wizard_step_definitions_on_wizard_id_and_step_number", unique: true + t.index ["wizard_id"], name: "by_step_definition_wizard" + end + + create_table "better_together_wizard_steps", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "wizard_id", null: false + t.uuid "wizard_step_definition_id", null: false + t.uuid "creator_id" + t.string "identifier", limit: 100, null: false + t.boolean "completed", default: false + t.integer "step_number", null: false + t.index ["creator_id"], name: "by_step_creator" + t.index ["identifier"], name: "by_step_identifier" + t.index ["wizard_id", "identifier", "creator_id"], name: "index_unique_wizard_steps", unique: true, where: "(completed IS FALSE)" + t.index ["wizard_id", "step_number"], name: "index_wizard_steps_on_wizard_id_and_step_number" + t.index ["wizard_id"], name: "by_step_wizard" + t.index ["wizard_step_definition_id"], name: "by_step_wizard_step_definition" + end + + create_table "better_together_wizards", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "identifier", limit: 100, null: false + t.boolean "protected", default: false, null: false + t.string "slug", null: false + t.integer "max_completions", default: 0, null: false + t.integer "current_completions", default: 0, null: false + t.datetime "first_completed_at" + t.datetime "last_completed_at" + t.text "success_message", default: "Thank you. You have successfully completed the wizard", null: false + t.string "success_path", default: "/", null: false + t.index ["identifier"], name: "index_better_together_wizards_on_identifier", unique: true + t.index ["slug"], name: "index_better_together_wizards_on_slug", unique: true + end + + create_table "friendly_id_slugs", force: :cascade do |t| + t.string "slug", null: false + t.uuid "sluggable_id", null: false + t.string "sluggable_type", null: false + t.string "scope" + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "locale", null: false + t.index ["locale"], name: "index_friendly_id_slugs_on_locale" + t.index ["slug", "sluggable_type", "locale"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_locale" + t.index ["slug", "sluggable_type", "scope", "locale"], name: "index_friendly_id_slugs_unique", unique: true + t.index ["sluggable_type", "sluggable_id"], name: "by_sluggable" + end + + create_table "mobility_string_translations", force: :cascade do |t| + t.string "locale", null: false + t.string "key", null: false + t.string "value" + t.string "translatable_type" + t.uuid "translatable_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_string_translations_on_translatable_attribute" + t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_string_translations_on_keys", unique: true + t.index ["translatable_type", "key", "value", "locale"], name: "index_mobility_string_translations_on_query_keys" + end + + create_table "mobility_text_translations", force: :cascade do |t| + t.string "locale", null: false + t.string "key", null: false + t.text "value" + t.string "translatable_type" + t.uuid "translatable_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_text_translations_on_translatable_attribute" + t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_text_translations_on_keys", unique: true + end + + create_table "noticed_events", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "type" + t.string "record_type" + t.uuid "record_id" + t.jsonb "params" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "notifications_count" + t.index ["record_type", "record_id"], name: "index_noticed_events_on_record" + end + + create_table "noticed_notifications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "type" + t.uuid "event_id", null: false + t.string "recipient_type", null: false + t.uuid "recipient_id", null: false + t.datetime "read_at", precision: nil + t.datetime "seen_at", precision: nil + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["event_id"], name: "index_noticed_notifications_on_event_id" + t.index ["recipient_type", "recipient_id"], name: "index_noticed_notifications_on_recipient" + end + + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "better_together_communities", "better_together_people", column: "creator_id" + add_foreign_key "better_together_conversation_participants", "better_together_conversations", column: "conversation_id" + add_foreign_key "better_together_conversation_participants", "better_together_people", column: "person_id" + add_foreign_key "better_together_conversations", "better_together_people", column: "creator_id" + add_foreign_key "better_together_geography_continents", "better_together_communities", column: "community_id" + add_foreign_key "better_together_geography_countries", "better_together_communities", column: "community_id" + add_foreign_key "better_together_geography_country_continents", "better_together_geography_continents", column: "continent_id" + add_foreign_key "better_together_geography_country_continents", "better_together_geography_countries", column: "country_id" + add_foreign_key "better_together_geography_region_settlements", "better_together_geography_regions", column: "region_id" + add_foreign_key "better_together_geography_region_settlements", "better_together_geography_settlements", column: "settlement_id" + add_foreign_key "better_together_geography_regions", "better_together_communities", column: "community_id" + add_foreign_key "better_together_geography_regions", "better_together_geography_countries", column: "country_id" + add_foreign_key "better_together_geography_regions", "better_together_geography_states", column: "state_id" + add_foreign_key "better_together_geography_settlements", "better_together_communities", column: "community_id" + add_foreign_key "better_together_geography_settlements", "better_together_geography_countries", column: "country_id" + add_foreign_key "better_together_geography_settlements", "better_together_geography_states", column: "state_id" + add_foreign_key "better_together_geography_states", "better_together_communities", column: "community_id" + add_foreign_key "better_together_geography_states", "better_together_geography_countries", column: "country_id" + add_foreign_key "better_together_messages", "better_together_conversations", column: "conversation_id" + add_foreign_key "better_together_messages", "better_together_people", column: "sender_id" + add_foreign_key "better_together_navigation_items", "better_together_navigation_areas", column: "navigation_area_id" + add_foreign_key "better_together_navigation_items", "better_together_navigation_items", column: "parent_id" + add_foreign_key "better_together_people", "better_together_communities", column: "community_id" + add_foreign_key "better_together_person_community_memberships", "better_together_communities", column: "joinable_id" + add_foreign_key "better_together_person_community_memberships", "better_together_people", column: "member_id" + add_foreign_key "better_together_person_community_memberships", "better_together_roles", column: "role_id" + add_foreign_key "better_together_person_platform_memberships", "better_together_people", column: "member_id" + add_foreign_key "better_together_person_platform_memberships", "better_together_platforms", column: "joinable_id" + add_foreign_key "better_together_person_platform_memberships", "better_together_roles", column: "role_id" + add_foreign_key "better_together_platform_invitations", "better_together_people", column: "invitee_id" + add_foreign_key "better_together_platform_invitations", "better_together_people", column: "inviter_id" + add_foreign_key "better_together_platform_invitations", "better_together_platforms", column: "invitable_id" + add_foreign_key "better_together_platform_invitations", "better_together_roles", column: "community_role_id" + add_foreign_key "better_together_platform_invitations", "better_together_roles", column: "platform_role_id" + add_foreign_key "better_together_platforms", "better_together_communities", column: "community_id" + add_foreign_key "better_together_role_resource_permissions", "better_together_resource_permissions", column: "resource_permission_id" + add_foreign_key "better_together_role_resource_permissions", "better_together_roles", column: "role_id" + add_foreign_key "better_together_wizard_step_definitions", "better_together_wizards", column: "wizard_id" + add_foreign_key "better_together_wizard_steps", "better_together_people", column: "creator_id" + add_foreign_key "better_together_wizard_steps", "better_together_wizard_step_definitions", column: "wizard_step_definition_id" + add_foreign_key "better_together_wizard_steps", "better_together_wizards", column: "wizard_id" end From 0ca869f6d3363c61136130d88ebfd1b5a0eb8504 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Tue, 3 Sep 2024 10:58:07 -0230 Subject: [PATCH 2/7] Update sidekiq config to use env prefixed queue names --- config/sidekiq.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 1faab33..130ee31 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -1,15 +1,21 @@ default: &default url: <%= ENV["REDIS_URL"] || 'redis://localhost:6379' %> - queues: - - default - - mailers development: <<: *default verbose: true + queues: + - default + - mailers test: <<: *default + queues: + - default + - mailers production: - <<: *default \ No newline at end of file + <<: *default + queues: + - better_together_production_default + - better_together_production_mailers \ No newline at end of file From 5b5be0d1a385c68b8d2398873187c3cc538e8bc3 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Mon, 9 Sep 2024 23:36:24 -0230 Subject: [PATCH 3/7] Ensure that the default root path for the better together app is the home page from the community engine. Closes better-together-org/community-engine-rails#637 --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index d90c306..d14e78f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,6 @@ Rails.application.routes.draw do get 'healthcheck', to: 'healthcheck#index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - root 'better_together/static_pages#community_engine' + root to: 'better_together/pages#show', defaults: { path: 'home-page' }, as: :home_page mount BetterTogether::Engine => '/' end From 85781d46d4f0d8a8b82c55c614fbb8378cbcc162 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Mon, 9 Sep 2024 23:38:07 -0230 Subject: [PATCH 4/7] Update better_together gem to add expanded page builder with content blocks and initial elasticsearch support --- .env.dev | 2 + Gemfile.lock | 53 +++++++++++++++---- ...gether_navigation_items.better_together.rb | 9 ++++ ...m_better_together_pages.better_together.rb | 10 ++++ ...together_content_blocks.better_together.rb | 21 ++++++++ ...her_content_page_blocks.better_together.rb | 18 +++++++ db/schema.rb | 36 +++++++++++-- docker-compose.yml | 21 ++++++++ 8 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 db/migrate/20240910015047_add_route_name_to_better_together_navigation_items.better_together.rb create mode 100644 db/migrate/20240910015048_remove_unused_columns_from_better_together_pages.better_together.rb create mode 100644 db/migrate/20240910015049_create_better_together_content_blocks.better_together.rb create mode 100644 db/migrate/20240910015050_create_better_together_content_page_blocks.better_together.rb diff --git a/.env.dev b/.env.dev index 9addbbe..b2c387c 100644 --- a/.env.dev +++ b/.env.dev @@ -1,6 +1,8 @@ ALLOWED_HOSTS=http://localhost:3001 APP_HOST=http://localhost:3001 BASE_URL=http://localhost:3001 +ES_PORT='9202' +ES_HOST='http://elasticsearch' POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_HOST=better-together-db diff --git a/Gemfile.lock b/Gemfile.lock index f125614..2680fcc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,10 @@ GIT remote: https://github.com/better-together-org/community-engine-rails.git - revision: 7178ef418172ba2b9f7fb27ab00dcd2687ff0ebd + revision: 474effc677e83b738826304aedda6c8fe7d86026 branch: wip/new-to-nl specs: better_together (0.5.0) + active_storage_validations activerecord-import activerecord-postgis-adapter bootstrap (~> 5.3.2) @@ -11,6 +12,8 @@ GIT devise devise-i18n devise-jwt + elasticsearch-model (~> 7) + elasticsearch-rails (~> 7) font-awesome-sass (~> 6.5) friendly_id (>= 5.2, < 5.6) friendly_id-mobility (~> 1.0.4) @@ -22,7 +25,7 @@ GIT mobility-actiontext (~> 1.1) noticed premailer-rails - pundit (>= 2.1, < 2.4) + pundit (>= 2.1, < 2.5) pundit-resources rack-cors (>= 1.1.1, < 2.1.0) rails (>= 5.2.2, < 7.2.0) @@ -104,6 +107,11 @@ GEM erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) + active_storage_validations (1.1.4) + activejob (>= 5.2.0) + activemodel (>= 5.2.0) + activestorage (>= 5.2.0) + activesupport (>= 5.2.0) activejob (7.1.4) activesupport (= 7.1.4) globalid (>= 0.3.6) @@ -113,7 +121,7 @@ GEM activemodel (= 7.1.4) activesupport (= 7.1.4) timeout (>= 0.4.0) - activerecord-import (1.8.0) + activerecord-import (1.8.1) activerecord (>= 4.2) activerecord-postgis-adapter (9.0.2) activerecord (~> 7.1.0) @@ -253,6 +261,20 @@ GEM dry-core (1.0.1) concurrent-ruby (~> 1.0) zeitwerk (~> 2.6) + elasticsearch (7.17.11) + elasticsearch-api (= 7.17.11) + elasticsearch-transport (= 7.17.11) + elasticsearch-api (7.17.11) + multi_json + elasticsearch-model (7.2.1) + activesupport (> 3) + elasticsearch (~> 7) + hashie + elasticsearch-rails (7.2.1) + elasticsearch-transport (7.17.11) + base64 + faraday (>= 1, < 3) + multi_json erubi (1.13.0) excon (0.111.0) execjs (2.9.1) @@ -263,6 +285,11 @@ GEM railties (>= 5.0.0) faker (3.4.2) i18n (>= 1.8.11, < 2) + faraday (2.11.0) + faraday-net_http (>= 2.0, < 3.4) + logger + faraday-net_http (3.3.0) + net-http ffi (1.17.0-x86_64-linux-gnu) fog-aws (3.25.0) base64 (~> 0.2.0) @@ -296,6 +323,7 @@ GEM google-protobuf (4.28.0-x86_64-linux) bigdecimal rake (>= 13) + hashie (5.0.0) htmlentities (4.3.4) http-accept (1.7.0) http-cookie (1.0.5) @@ -358,7 +386,9 @@ GEM msgpack (1.7.2) multi_json (1.15.0) mutex_m (0.2.0) - net-imap (0.4.15) + net-http (0.4.1) + uri + net-imap (0.4.16) date net-protocol net-pop (0.1.2) @@ -371,7 +401,7 @@ GEM nio4r (2.7.3) nokogiri (1.16.7-x86_64-linux) racc (~> 1.4) - noticed (2.4.1) + noticed (2.4.3) rails (>= 6.1.0) optimist (3.1.0) orm_adapter (0.5.0) @@ -397,7 +427,7 @@ GEM public_suffix (6.0.1) puma (6.4.2) nio4r (~> 2.0) - pundit (2.3.2) + pundit (2.4.0) activesupport (>= 3.0.0) racc (1.8.1) rack (3.1.7) @@ -468,7 +498,7 @@ GEM activemodel (>= 5.0) reform (>= 2.3.1, < 3.0.0) regexp_parser (2.9.2) - reline (0.5.9) + reline (0.5.10) io-console (~> 0.5) representable (3.2.0) declarative (< 0.1.0) @@ -546,12 +576,12 @@ GEM ffi (~> 1.12) logger rubyzip (2.3.2) - sass-embedded (1.77.8-x86_64-linux-gnu) - google-protobuf (~> 4.26) + sass-embedded (1.78.0-x86_64-linux-gnu) + google-protobuf (~> 4.27) sassc (2.4.0) ffi (~> 1.9) - sassc-embedded (1.77.8) - sass-embedded (~> 1.77) + sassc-embedded (1.78.0) + sass-embedded (~> 1.78) selenium-webdriver (4.24.0) base64 (~> 0.2) logger (~> 1.4) @@ -620,6 +650,7 @@ GEM execjs (>= 0.3.0, < 3) unf (0.2.0) unicode-display_width (2.5.0) + uri (0.13.1) virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) diff --git a/db/migrate/20240910015047_add_route_name_to_better_together_navigation_items.better_together.rb b/db/migrate/20240910015047_add_route_name_to_better_together_navigation_items.better_together.rb new file mode 100644 index 0000000..86ea0c2 --- /dev/null +++ b/db/migrate/20240910015047_add_route_name_to_better_together_navigation_items.better_together.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240905203412) +# Allows for dynamic dispatch of url helpers instead of hard-coded urls +class AddRouteNameToBetterTogetherNavigationItems < ActiveRecord::Migration[7.1] + def change + add_column :better_together_navigation_items, :route_name, :string + end +end diff --git a/db/migrate/20240910015048_remove_unused_columns_from_better_together_pages.better_together.rb b/db/migrate/20240910015048_remove_unused_columns_from_better_together_pages.better_together.rb new file mode 100644 index 0000000..2a8cdaa --- /dev/null +++ b/db/migrate/20240910015048_remove_unused_columns_from_better_together_pages.better_together.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240906132628) +# Cleans up unused columns on pages table +class RemoveUnusedColumnsFromBetterTogetherPages < ActiveRecord::Migration[7.1] + def change + remove_column :better_together_pages, :language + remove_column :better_together_pages, :published + end +end diff --git a/db/migrate/20240910015049_create_better_together_content_blocks.better_together.rb b/db/migrate/20240910015049_create_better_together_content_blocks.better_together.rb new file mode 100644 index 0000000..ed2aa81 --- /dev/null +++ b/db/migrate/20240910015049_create_better_together_content_blocks.better_together.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240906142416) +# Creates blocks table to allow for robust page builder content +class CreateBetterTogetherContentBlocks < ActiveRecord::Migration[7.1] + def change # rubocop:todo Metrics/MethodLength + create_bt_table :blocks, prefix: 'better_together_content' do |t| + t.string :type, null: false + + t.bt_identifier(null: true) + + t.jsonb :accessibility_attributes, null: false, default: {} + t.jsonb :content_settings, null: false, default: {} + t.jsonb :css_settings, null: false, default: {} + t.jsonb :data_attributes, null: false, default: {} + t.jsonb :html_attributes, null: false, default: {} + t.jsonb :layout_settings, null: false, default: {} + t.jsonb :media_settings, null: false, default: {} + end + end +end diff --git a/db/migrate/20240910015050_create_better_together_content_page_blocks.better_together.rb b/db/migrate/20240910015050_create_better_together_content_page_blocks.better_together.rb new file mode 100644 index 0000000..84911b6 --- /dev/null +++ b/db/migrate/20240910015050_create_better_together_content_page_blocks.better_together.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# This migration comes from better_together (originally 20240906152410) +# Created join table between pages and blocks +class CreateBetterTogetherContentPageBlocks < ActiveRecord::Migration[7.1] + def change + create_bt_table :page_blocks, prefix: 'better_together_content' do |t| + t.bt_references :page, null: false + t.bt_references :block, null: false, table_prefix: 'better_together_content' + t.bt_position + end + + add_index :better_together_content_page_blocks, %i[page_id block_id], unique: true, + name: 'content_page_blocks_on_page_and_block' + add_index :better_together_content_page_blocks, %i[page_id block_id position], + name: 'content_page_blocks_on_page_block_and_position' + end +end diff --git a/db/schema.rb b/db/schema.rb index 12cd4f6..1f52231 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[7.1].define(version: 2024_09_03_114604) do +ActiveRecord::Schema[7.1].define(version: 2024_09_10_015050) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -72,6 +72,34 @@ t.index ["slug"], name: "index_better_together_communities_on_slug", unique: true end + create_table "better_together_content_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "type", null: false + t.string "identifier", limit: 100 + t.jsonb "accessibility_attributes", default: {}, null: false + t.jsonb "content_settings", default: {}, null: false + t.jsonb "css_settings", default: {}, null: false + t.jsonb "data_attributes", default: {}, null: false + t.jsonb "html_attributes", default: {}, null: false + t.jsonb "layout_settings", default: {}, null: false + t.jsonb "media_settings", default: {}, null: false + end + + create_table "better_together_content_page_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "lock_version", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "page_id", null: false + t.uuid "block_id", null: false + t.integer "position", null: false + t.index ["block_id"], name: "index_better_together_content_page_blocks_on_block_id" + t.index ["page_id", "block_id", "position"], name: "content_page_blocks_on_page_block_and_position" + t.index ["page_id", "block_id"], name: "content_page_blocks_on_page_and_block", unique: true + t.index ["page_id"], name: "index_better_together_content_page_blocks_on_page_id" + end + create_table "better_together_conversation_participants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "lock_version", default: 0, null: false t.datetime "created_at", null: false @@ -262,6 +290,7 @@ t.string "item_type", null: false t.string "linkable_type" t.uuid "linkable_id" + t.string "route_name" t.index ["identifier"], name: "index_better_together_navigation_items_on_identifier", unique: true t.index ["linkable_type", "linkable_id"], name: "by_linkable" t.index ["navigation_area_id", "parent_id", "position"], name: "navigation_items_area_position", unique: true @@ -279,15 +308,12 @@ t.string "slug", null: false t.text "meta_description" t.string "keywords" - t.boolean "published" t.datetime "published_at" t.string "privacy", default: "public", null: false t.string "layout" t.string "template" - t.string "language", default: "en" t.index ["identifier"], name: "index_better_together_pages_on_identifier", unique: true t.index ["privacy"], name: "by_page_privacy" - t.index ["published"], name: "by_page_publication_status" t.index ["published_at"], name: "by_page_publication_date" t.index ["slug"], name: "index_better_together_pages_on_slug", unique: true end @@ -573,6 +599,8 @@ add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "better_together_communities", "better_together_people", column: "creator_id" + add_foreign_key "better_together_content_page_blocks", "better_together_content_blocks", column: "block_id" + add_foreign_key "better_together_content_page_blocks", "better_together_pages", column: "page_id" add_foreign_key "better_together_conversation_participants", "better_together_conversations", column: "conversation_id" add_foreign_key "better_together_conversation_participants", "better_together_people", column: "person_id" add_foreign_key "better_together_conversations", "better_together_people", column: "creator_id" diff --git a/docker-compose.yml b/docker-compose.yml index c1e59cd..de89231 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ version: '3.6' volumes: bt-bundler-gems: bt-db-data: + bt-elasticsearch: bt-redis: x-env-info: &env-info @@ -39,6 +40,26 @@ services: - bt-db-data:/var/lib/postgresql/data ports: - "5435:5432" + + + elasticsearch: + container_name: better-together-elasticsearch + image: elasticsearch:7.17.23 + environment: + - node.name=elasticsearch + - cluster.name=better-together-es + - discovery.seed_hosts=elasticsearch + - discovery.type=single-node + - bootstrap.memory_lock=true + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + ports: + - 9202:9200 + ulimits: + memlock: + soft: -1 + hard: -1 + volumes: + - bt-elasticsearch:/usr/share/elasticsearch/data sidekiq: <<: *app-shared From 5fd41ded30a336ba9603d4f7522126c6a0c0dcb1 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Wed, 11 Sep 2024 16:38:41 -0230 Subject: [PATCH 5/7] Update better_together to use v0.6.0 --- Gemfile | 6 +++--- Gemfile.lock | 8 ++++---- docker-compose.yml | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 162d0fe..0cfae78 100644 --- a/Gemfile +++ b/Gemfile @@ -9,12 +9,12 @@ gem 'asset_sync' gem 'aws-sdk-s3', require: false # Use the published version of better_together for production -gem 'better_together', '~> 0.5.0', +gem 'better_together', '~> 0.6.0', github: 'better-together-org/community-engine-rails', - branch: 'wip/new-to-nl' + branch: 'main' # Use the local development version of better_together -# gem 'better_together', '~> 0.4.1', path: '/community-engine' +# gem 'better_together', path: '/community-engine' # bcrypt for secure password handling gem 'bcrypt', '~> 3.1.20' diff --git a/Gemfile.lock b/Gemfile.lock index 2680fcc..67f8acd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ GIT remote: https://github.com/better-together-org/community-engine-rails.git - revision: 474effc677e83b738826304aedda6c8fe7d86026 - branch: wip/new-to-nl + revision: 28d4080a4334a66e64eacab251186b737085cd17 + branch: main specs: - better_together (0.5.0) + better_together (0.6.0) active_storage_validations activerecord-import activerecord-postgis-adapter @@ -688,7 +688,7 @@ DEPENDENCIES aws-sdk-s3 bcrypt (~> 3.1.20) better_errors - better_together (~> 0.5.0)! + better_together (~> 0.6.0)! binding_of_caller bootsnap (>= 1.7.0) brakeman diff --git a/docker-compose.yml b/docker-compose.yml index de89231..193a422 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,7 +41,6 @@ services: ports: - "5435:5432" - elasticsearch: container_name: better-together-elasticsearch image: elasticsearch:7.17.23 From 828fb75d6e3afd4a0c18bed3f6aba0bf15aee9a7 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Wed, 11 Sep 2024 16:40:25 -0230 Subject: [PATCH 6/7] Add elasticsearch to github action workflow --- .github/workflows/rails.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/rails.yml b/.github/workflows/rails.yml index f8cc359..8a544c7 100644 --- a/.github/workflows/rails.yml +++ b/.github/workflows/rails.yml @@ -18,9 +18,21 @@ jobs: POSTGRES_DB: rails_test POSTGRES_USER: rails POSTGRES_PASSWORD: password + elasticsearch: + image: elasticsearch:7.17.23 + ports: + - "9200:9200" + env: + "node.name": elasticsearch + "cluster.name": better-together-es + "discovery.seed_hosts": elasticsearch + "discovery.type": single-node + "bootstrap.memory_lock": true + "ES_JAVA_OPTS": "-Xms512m -Xmx512m" env: RAILS_ENV: test DATABASE_URL: "postgres://rails:password@localhost:5432/rails_test" + ES_HOST: "http://localhost" steps: - name: Checkout code uses: actions/checkout@v3 From 14cecaafc2d8f1274ba011de9c869d0016805efe Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Wed, 11 Sep 2024 16:46:08 -0230 Subject: [PATCH 7/7] rubocop fixes --- ...er_platform_invitations.better_together.rb | 4 +- ...m_better_together_navigation_areas_name.rb | 3 + db/schema.rb | 1314 +++++++++-------- 3 files changed, 689 insertions(+), 632 deletions(-) diff --git a/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb b/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb index 1083b49..e422d69 100644 --- a/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb +++ b/db/migrate/20240903112741_create_better_together_platform_invitations.better_together.rb @@ -81,8 +81,8 @@ def change # rubocop:todo Metrics/AbcSize, Metrics/MethodLength add_index :better_together_platform_invitations, %i[invitee_email invitable_id], unique: true add_index :better_together_platform_invitations, %i[invitable_id status], - name: "index_platform_invitations_on_invitable_id_and_status" + name: 'index_platform_invitations_on_invitable_id_and_status' add_index :better_together_platform_invitations, :invitee_email, where: "status = 'pending'", - name: "index_pending_invitations_on_invitee_email" + name: 'index_pending_invitations_on_invitee_email' end end diff --git a/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb b/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb index 1186986..79b9d9d 100644 --- a/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb +++ b/db/migrate/20240903114604_remove_column_null_constraint_from_better_together_navigation_areas_name.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true + +# Removes unused null constraint class RemoveColumnNullConstraintFromBetterTogetherNavigationAreasName < ActiveRecord::Migration[7.1] def up change_column_null :better_together_navigation_areas, :name, true diff --git a/db/schema.rb b/db/schema.rb index 1f52231..4cf5c94 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -10,635 +12,687 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_09_10_015050) do +ActiveRecord::Schema[7.1].define(version: 20_240_910_015_050) do # rubocop:todo Metrics/BlockLength # These are extensions that must be enabled in order to support this database - enable_extension "pgcrypto" - enable_extension "plpgsql" - enable_extension "postgis" - - create_table "action_text_rich_texts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "name", null: false - t.text "body" - t.string "record_type", null: false - t.uuid "record_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "locale", null: false - t.index ["record_type", "record_id", "name", "locale"], name: "index_action_text_rich_texts_uniqueness", unique: true - end - - create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "name", null: false - t.string "record_type", null: false - t.uuid "record_id", null: false - t.uuid "blob_id", null: false - t.datetime "created_at", null: false - t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" - t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true - end - - create_table "active_storage_blobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "key", null: false - t.string "filename", null: false - t.string "content_type" - t.text "metadata" - t.string "service_name", null: false - t.bigint "byte_size", null: false - t.string "checksum" - t.datetime "created_at", null: false - t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true - end - - create_table "active_storage_variant_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "blob_id", null: false - t.string "variation_digest", null: false - t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true - end - - create_table "better_together_communities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "host", default: false, null: false - t.boolean "protected", default: false, null: false - t.string "privacy", limit: 50, default: "public", null: false - t.string "slug", null: false - t.uuid "creator_id" - t.index ["creator_id"], name: "by_creator" - t.index ["host"], name: "index_better_together_communities_on_host", unique: true, where: "(host IS TRUE)" - t.index ["identifier"], name: "index_better_together_communities_on_identifier", unique: true - t.index ["privacy"], name: "by_community_privacy" - t.index ["slug"], name: "index_better_together_communities_on_slug", unique: true - end - - create_table "better_together_content_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "type", null: false - t.string "identifier", limit: 100 - t.jsonb "accessibility_attributes", default: {}, null: false - t.jsonb "content_settings", default: {}, null: false - t.jsonb "css_settings", default: {}, null: false - t.jsonb "data_attributes", default: {}, null: false - t.jsonb "html_attributes", default: {}, null: false - t.jsonb "layout_settings", default: {}, null: false - t.jsonb "media_settings", default: {}, null: false - end - - create_table "better_together_content_page_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "page_id", null: false - t.uuid "block_id", null: false - t.integer "position", null: false - t.index ["block_id"], name: "index_better_together_content_page_blocks_on_block_id" - t.index ["page_id", "block_id", "position"], name: "content_page_blocks_on_page_block_and_position" - t.index ["page_id", "block_id"], name: "content_page_blocks_on_page_and_block", unique: true - t.index ["page_id"], name: "index_better_together_content_page_blocks_on_page_id" - end - - create_table "better_together_conversation_participants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "conversation_id", null: false - t.uuid "person_id", null: false - t.index ["conversation_id"], name: "idx_on_conversation_id_30b3b70bad" - t.index ["person_id"], name: "index_better_together_conversation_participants_on_person_id" - end - - create_table "better_together_conversations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "title", null: false - t.uuid "creator_id", null: false - t.index ["creator_id"], name: "index_better_together_conversations_on_creator_id" - end - - create_table "better_together_geography_continents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.uuid "community_id", null: false - t.string "slug", null: false - t.index ["community_id"], name: "by_geography_continent_community" - t.index ["identifier"], name: "index_better_together_geography_continents_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_geography_continents_on_slug", unique: true - end - - create_table "better_together_geography_countries", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.string "iso_code", limit: 2, null: false - t.boolean "protected", default: false, null: false - t.uuid "community_id", null: false - t.string "slug", null: false - t.index ["community_id"], name: "by_geography_country_community" - t.index ["identifier"], name: "index_better_together_geography_countries_on_identifier", unique: true - t.index ["iso_code"], name: "index_better_together_geography_countries_on_iso_code", unique: true - t.index ["slug"], name: "index_better_together_geography_countries_on_slug", unique: true - end - - create_table "better_together_geography_country_continents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "country_id" - t.uuid "continent_id" - t.index ["continent_id"], name: "country_continent_by_continent" - t.index ["country_id", "continent_id"], name: "index_country_continents_on_country_and_continent", unique: true - t.index ["country_id"], name: "country_continent_by_country" - end - - create_table "better_together_geography_region_settlements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "protected", default: false, null: false - t.uuid "region_id" - t.uuid "settlement_id" - t.index ["region_id"], name: "bt_region_settlement_by_region" - t.index ["settlement_id"], name: "bt_region_settlement_by_settlement" - end - - create_table "better_together_geography_regions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.uuid "community_id", null: false - t.uuid "country_id" - t.uuid "state_id" - t.string "slug", null: false - t.string "type", default: "BetterTogether::Geography::Region", null: false - t.index ["community_id"], name: "by_geography_region_community" - t.index ["country_id"], name: "index_better_together_geography_regions_on_country_id" - t.index ["identifier"], name: "index_better_together_geography_regions_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_geography_regions_on_slug", unique: true - t.index ["state_id"], name: "index_better_together_geography_regions_on_state_id" - end - - create_table "better_together_geography_settlements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.uuid "community_id", null: false - t.uuid "country_id" - t.uuid "state_id" - t.string "slug", null: false - t.index ["community_id"], name: "by_geography_settlement_community" - t.index ["country_id"], name: "index_better_together_geography_settlements_on_country_id" - t.index ["identifier"], name: "index_better_together_geography_settlements_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_geography_settlements_on_slug", unique: true - t.index ["state_id"], name: "index_better_together_geography_settlements_on_state_id" - end - - create_table "better_together_geography_states", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.string "iso_code", limit: 5, null: false - t.boolean "protected", default: false, null: false - t.uuid "community_id", null: false - t.uuid "country_id" - t.string "slug", null: false - t.index ["community_id"], name: "by_geography_state_community" - t.index ["country_id"], name: "index_better_together_geography_states_on_country_id" - t.index ["identifier"], name: "index_better_together_geography_states_on_identifier", unique: true - t.index ["iso_code"], name: "index_better_together_geography_states_on_iso_code", unique: true - t.index ["slug"], name: "index_better_together_geography_states_on_slug", unique: true - end - - create_table "better_together_identifications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "active", null: false - t.string "identity_type", null: false - t.uuid "identity_id", null: false - t.string "agent_type", null: false - t.uuid "agent_id", null: false - t.index ["active", "agent_type", "agent_id"], name: "active_identification", unique: true - t.index ["active"], name: "by_active_state" - t.index ["agent_type", "agent_id"], name: "by_agent" - t.index ["identity_type", "identity_id", "agent_type", "agent_id"], name: "unique_identification", unique: true - t.index ["identity_type", "identity_id"], name: "by_identity" - end - - create_table "better_together_jwt_denylists", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "jti" - t.datetime "exp" - t.index ["jti"], name: "index_better_together_jwt_denylists_on_jti" - end - - create_table "better_together_messages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.text "content", null: false - t.uuid "sender_id", null: false - t.uuid "conversation_id", null: false - t.index ["conversation_id"], name: "index_better_together_messages_on_conversation_id" - t.index ["sender_id"], name: "index_better_together_messages_on_sender_id" - end - - create_table "better_together_navigation_areas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.string "slug", null: false - t.boolean "visible", default: true, null: false - t.string "name" - t.string "style" - t.string "navigable_type" - t.bigint "navigable_id" - t.index ["identifier"], name: "index_better_together_navigation_areas_on_identifier", unique: true - t.index ["navigable_type", "navigable_id"], name: "by_navigable" - t.index ["slug"], name: "index_better_together_navigation_areas_on_slug", unique: true - end - - create_table "better_together_navigation_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.integer "position", null: false - t.boolean "protected", default: false, null: false - t.string "slug", null: false - t.boolean "visible", default: true, null: false - t.uuid "navigation_area_id", null: false - t.uuid "parent_id" - t.string "url" - t.string "icon" - t.string "item_type", null: false - t.string "linkable_type" - t.uuid "linkable_id" - t.string "route_name" - t.index ["identifier"], name: "index_better_together_navigation_items_on_identifier", unique: true - t.index ["linkable_type", "linkable_id"], name: "by_linkable" - t.index ["navigation_area_id", "parent_id", "position"], name: "navigation_items_area_position", unique: true - t.index ["navigation_area_id"], name: "index_better_together_navigation_items_on_navigation_area_id" - t.index ["parent_id"], name: "by_nav_item_parent" - t.index ["slug"], name: "index_better_together_navigation_items_on_slug", unique: true - end - - create_table "better_together_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.string "slug", null: false - t.text "meta_description" - t.string "keywords" - t.datetime "published_at" - t.string "privacy", default: "public", null: false - t.string "layout" - t.string "template" - t.index ["identifier"], name: "index_better_together_pages_on_identifier", unique: true - t.index ["privacy"], name: "by_page_privacy" - t.index ["published_at"], name: "by_page_publication_date" - t.index ["slug"], name: "index_better_together_pages_on_slug", unique: true - end - - create_table "better_together_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.string "slug", null: false - t.uuid "community_id", null: false - t.jsonb "preferences", default: {}, null: false - t.index ["community_id"], name: "by_person_community" - t.index ["identifier"], name: "index_better_together_people_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_people_on_slug", unique: true - end - - create_table "better_together_person_community_memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "member_id", null: false - t.uuid "joinable_id", null: false - t.uuid "role_id", null: false - t.index ["joinable_id", "member_id", "role_id"], name: "unique_person_community_membership_member_role", unique: true - t.index ["joinable_id"], name: "person_community_membership_by_joinable" - t.index ["member_id"], name: "person_community_membership_by_member" - t.index ["role_id"], name: "person_community_membership_by_role" - end - - create_table "better_together_person_platform_memberships", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "member_id", null: false - t.uuid "joinable_id", null: false - t.uuid "role_id", null: false - t.index ["joinable_id", "member_id", "role_id"], name: "unique_person_platform_membership_member_role", unique: true - t.index ["joinable_id"], name: "person_platform_membership_by_joinable" - t.index ["member_id"], name: "person_platform_membership_by_member" - t.index ["role_id"], name: "person_platform_membership_by_role" - end - - create_table "better_together_platform_invitations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "community_role_id", null: false - t.string "invitee_email", null: false - t.uuid "invitable_id", null: false - t.uuid "invitee_id" - t.uuid "inviter_id", null: false - t.uuid "platform_role_id" - t.string "status", limit: 20, null: false - t.string "locale", limit: 5, default: "en", null: false - t.string "token", limit: 24, null: false - t.datetime "valid_from", null: false - t.datetime "valid_until" - t.datetime "last_sent" - t.datetime "accepted_at" - t.index ["community_role_id"], name: "platform_invitations_by_community_role" - t.index ["invitable_id", "status"], name: "index_platform_invitations_on_invitable_id_and_status" - t.index ["invitable_id"], name: "platform_invitations_by_invitable" - t.index ["invitee_email", "invitable_id"], name: "idx_on_invitee_email_invitable_id_5a7d642388", unique: true - t.index ["invitee_email"], name: "index_pending_invitations_on_invitee_email", where: "((status)::text = 'pending'::text)" - t.index ["invitee_email"], name: "platform_invitations_by_invitee_email" - t.index ["invitee_id"], name: "platform_invitations_by_invitee" - t.index ["inviter_id"], name: "platform_invitations_by_inviter" - t.index ["locale"], name: "platform_invitations_by_locale" - t.index ["platform_role_id"], name: "platform_invitations_by_platform_role" - t.index ["status"], name: "platform_invitations_by_status" - t.index ["token"], name: "platform_invitations_by_token", unique: true - t.index ["valid_from"], name: "platform_invitations_by_valid_from" - t.index ["valid_until"], name: "platform_invitations_by_valid_until" - end - - create_table "better_together_platforms", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "host", default: false, null: false - t.boolean "protected", default: false, null: false - t.string "privacy", limit: 50, default: "public", null: false - t.string "slug", null: false - t.uuid "community_id" - t.string "url", null: false - t.string "time_zone", null: false - t.jsonb "settings", default: {}, null: false - t.index ["community_id"], name: "by_platform_community" - t.index ["host"], name: "index_better_together_platforms_on_host", unique: true, where: "(host IS TRUE)" - t.index ["identifier"], name: "index_better_together_platforms_on_identifier", unique: true - t.index ["privacy"], name: "by_platform_privacy" - t.index ["slug"], name: "index_better_together_platforms_on_slug", unique: true - t.index ["url"], name: "index_better_together_platforms_on_url", unique: true - end - - create_table "better_together_resource_permissions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.integer "position", null: false - t.string "resource_type", null: false - t.string "slug", null: false - t.string "action", null: false - t.string "target", null: false - t.index ["identifier"], name: "index_better_together_resource_permissions_on_identifier", unique: true - t.index ["resource_type", "position"], name: "index_resource_permissions_on_resource_type_and_position", unique: true - t.index ["slug"], name: "index_better_together_resource_permissions_on_slug", unique: true - end - - create_table "better_together_role_resource_permissions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "role_id", null: false - t.uuid "resource_permission_id", null: false - t.index ["resource_permission_id"], name: "role_resource_permissions_resource_permission" - t.index ["role_id", "resource_permission_id"], name: "unique_role_resource_permission_index", unique: true - t.index ["role_id"], name: "role_resource_permissions_role" - end - - create_table "better_together_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.integer "position", null: false - t.string "resource_type", null: false - t.string "slug", null: false - t.index ["identifier"], name: "index_better_together_roles_on_identifier", unique: true - t.index ["resource_type", "position"], name: "index_roles_on_resource_type_and_position", unique: true - t.index ["slug"], name: "index_better_together_roles_on_slug", unique: true - end - - create_table "better_together_users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token" - t.datetime "locked_at" - t.index ["confirmation_token"], name: "index_better_together_users_on_confirmation_token", unique: true - t.index ["email"], name: "index_better_together_users_on_email", unique: true - t.index ["reset_password_token"], name: "index_better_together_users_on_reset_password_token", unique: true - t.index ["unlock_token"], name: "index_better_together_users_on_unlock_token", unique: true - end - - create_table "better_together_wizard_step_definitions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.string "slug", null: false - t.uuid "wizard_id", null: false - t.string "template" - t.string "form_class" - t.string "message", default: "Please complete this next step.", null: false - t.integer "step_number", null: false - t.index ["identifier"], name: "index_better_together_wizard_step_definitions_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_wizard_step_definitions_on_slug", unique: true - t.index ["wizard_id", "step_number"], name: "index_wizard_step_definitions_on_wizard_id_and_step_number", unique: true - t.index ["wizard_id"], name: "by_step_definition_wizard" - end - - create_table "better_together_wizard_steps", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.uuid "wizard_id", null: false - t.uuid "wizard_step_definition_id", null: false - t.uuid "creator_id" - t.string "identifier", limit: 100, null: false - t.boolean "completed", default: false - t.integer "step_number", null: false - t.index ["creator_id"], name: "by_step_creator" - t.index ["identifier"], name: "by_step_identifier" - t.index ["wizard_id", "identifier", "creator_id"], name: "index_unique_wizard_steps", unique: true, where: "(completed IS FALSE)" - t.index ["wizard_id", "step_number"], name: "index_wizard_steps_on_wizard_id_and_step_number" - t.index ["wizard_id"], name: "by_step_wizard" - t.index ["wizard_step_definition_id"], name: "by_step_wizard_step_definition" - end - - create_table "better_together_wizards", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "identifier", limit: 100, null: false - t.boolean "protected", default: false, null: false - t.string "slug", null: false - t.integer "max_completions", default: 0, null: false - t.integer "current_completions", default: 0, null: false - t.datetime "first_completed_at" - t.datetime "last_completed_at" - t.text "success_message", default: "Thank you. You have successfully completed the wizard", null: false - t.string "success_path", default: "/", null: false - t.index ["identifier"], name: "index_better_together_wizards_on_identifier", unique: true - t.index ["slug"], name: "index_better_together_wizards_on_slug", unique: true - end - - create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.uuid "sluggable_id", null: false - t.string "sluggable_type", null: false - t.string "scope" - t.integer "lock_version", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "locale", null: false - t.index ["locale"], name: "index_friendly_id_slugs_on_locale" - t.index ["slug", "sluggable_type", "locale"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_locale" - t.index ["slug", "sluggable_type", "scope", "locale"], name: "index_friendly_id_slugs_unique", unique: true - t.index ["sluggable_type", "sluggable_id"], name: "by_sluggable" - end - - create_table "mobility_string_translations", force: :cascade do |t| - t.string "locale", null: false - t.string "key", null: false - t.string "value" - t.string "translatable_type" - t.uuid "translatable_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_string_translations_on_translatable_attribute" - t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_string_translations_on_keys", unique: true - t.index ["translatable_type", "key", "value", "locale"], name: "index_mobility_string_translations_on_query_keys" - end - - create_table "mobility_text_translations", force: :cascade do |t| - t.string "locale", null: false - t.string "key", null: false - t.text "value" - t.string "translatable_type" - t.uuid "translatable_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_text_translations_on_translatable_attribute" - t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_text_translations_on_keys", unique: true - end - - create_table "noticed_events", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "type" - t.string "record_type" - t.uuid "record_id" - t.jsonb "params" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "notifications_count" - t.index ["record_type", "record_id"], name: "index_noticed_events_on_record" - end - - create_table "noticed_notifications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "type" - t.uuid "event_id", null: false - t.string "recipient_type", null: false - t.uuid "recipient_id", null: false - t.datetime "read_at", precision: nil - t.datetime "seen_at", precision: nil - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["event_id"], name: "index_noticed_notifications_on_event_id" - t.index ["recipient_type", "recipient_id"], name: "index_noticed_notifications_on_recipient" - end - - add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" - add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" - add_foreign_key "better_together_communities", "better_together_people", column: "creator_id" - add_foreign_key "better_together_content_page_blocks", "better_together_content_blocks", column: "block_id" - add_foreign_key "better_together_content_page_blocks", "better_together_pages", column: "page_id" - add_foreign_key "better_together_conversation_participants", "better_together_conversations", column: "conversation_id" - add_foreign_key "better_together_conversation_participants", "better_together_people", column: "person_id" - add_foreign_key "better_together_conversations", "better_together_people", column: "creator_id" - add_foreign_key "better_together_geography_continents", "better_together_communities", column: "community_id" - add_foreign_key "better_together_geography_countries", "better_together_communities", column: "community_id" - add_foreign_key "better_together_geography_country_continents", "better_together_geography_continents", column: "continent_id" - add_foreign_key "better_together_geography_country_continents", "better_together_geography_countries", column: "country_id" - add_foreign_key "better_together_geography_region_settlements", "better_together_geography_regions", column: "region_id" - add_foreign_key "better_together_geography_region_settlements", "better_together_geography_settlements", column: "settlement_id" - add_foreign_key "better_together_geography_regions", "better_together_communities", column: "community_id" - add_foreign_key "better_together_geography_regions", "better_together_geography_countries", column: "country_id" - add_foreign_key "better_together_geography_regions", "better_together_geography_states", column: "state_id" - add_foreign_key "better_together_geography_settlements", "better_together_communities", column: "community_id" - add_foreign_key "better_together_geography_settlements", "better_together_geography_countries", column: "country_id" - add_foreign_key "better_together_geography_settlements", "better_together_geography_states", column: "state_id" - add_foreign_key "better_together_geography_states", "better_together_communities", column: "community_id" - add_foreign_key "better_together_geography_states", "better_together_geography_countries", column: "country_id" - add_foreign_key "better_together_messages", "better_together_conversations", column: "conversation_id" - add_foreign_key "better_together_messages", "better_together_people", column: "sender_id" - add_foreign_key "better_together_navigation_items", "better_together_navigation_areas", column: "navigation_area_id" - add_foreign_key "better_together_navigation_items", "better_together_navigation_items", column: "parent_id" - add_foreign_key "better_together_people", "better_together_communities", column: "community_id" - add_foreign_key "better_together_person_community_memberships", "better_together_communities", column: "joinable_id" - add_foreign_key "better_together_person_community_memberships", "better_together_people", column: "member_id" - add_foreign_key "better_together_person_community_memberships", "better_together_roles", column: "role_id" - add_foreign_key "better_together_person_platform_memberships", "better_together_people", column: "member_id" - add_foreign_key "better_together_person_platform_memberships", "better_together_platforms", column: "joinable_id" - add_foreign_key "better_together_person_platform_memberships", "better_together_roles", column: "role_id" - add_foreign_key "better_together_platform_invitations", "better_together_people", column: "invitee_id" - add_foreign_key "better_together_platform_invitations", "better_together_people", column: "inviter_id" - add_foreign_key "better_together_platform_invitations", "better_together_platforms", column: "invitable_id" - add_foreign_key "better_together_platform_invitations", "better_together_roles", column: "community_role_id" - add_foreign_key "better_together_platform_invitations", "better_together_roles", column: "platform_role_id" - add_foreign_key "better_together_platforms", "better_together_communities", column: "community_id" - add_foreign_key "better_together_role_resource_permissions", "better_together_resource_permissions", column: "resource_permission_id" - add_foreign_key "better_together_role_resource_permissions", "better_together_roles", column: "role_id" - add_foreign_key "better_together_wizard_step_definitions", "better_together_wizards", column: "wizard_id" - add_foreign_key "better_together_wizard_steps", "better_together_people", column: "creator_id" - add_foreign_key "better_together_wizard_steps", "better_together_wizard_step_definitions", column: "wizard_step_definition_id" - add_foreign_key "better_together_wizard_steps", "better_together_wizards", column: "wizard_id" + enable_extension 'pgcrypto' + enable_extension 'plpgsql' + enable_extension 'postgis' + + create_table 'action_text_rich_texts', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.string 'name', null: false + t.text 'body' + t.string 'record_type', null: false + t.uuid 'record_id', null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'locale', null: false + t.index %w[record_type record_id name locale], name: 'index_action_text_rich_texts_uniqueness', + unique: true + end + + create_table 'active_storage_attachments', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.string 'name', null: false + t.string 'record_type', null: false + t.uuid 'record_id', null: false + t.uuid 'blob_id', null: false + t.datetime 'created_at', null: false + t.index ['blob_id'], name: 'index_active_storage_attachments_on_blob_id' + t.index %w[record_type record_id name blob_id], name: 'index_active_storage_attachments_uniqueness', + unique: true + end + + create_table 'active_storage_blobs', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.string 'key', null: false + t.string 'filename', null: false + t.string 'content_type' + t.text 'metadata' + t.string 'service_name', null: false + t.bigint 'byte_size', null: false + t.string 'checksum' + t.datetime 'created_at', null: false + t.index ['key'], name: 'index_active_storage_blobs_on_key', unique: true + end + + create_table 'active_storage_variant_records', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.uuid 'blob_id', null: false + t.string 'variation_digest', null: false + t.index %w[blob_id variation_digest], name: 'index_active_storage_variant_records_uniqueness', unique: true + end + + create_table 'better_together_communities', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'host', default: false, null: false + t.boolean 'protected', default: false, null: false + t.string 'privacy', limit: 50, default: 'public', null: false + t.string 'slug', null: false + t.uuid 'creator_id' + t.index ['creator_id'], name: 'by_creator' + t.index ['host'], name: 'index_better_together_communities_on_host', unique: true, where: '(host IS TRUE)' + t.index ['identifier'], name: 'index_better_together_communities_on_identifier', unique: true + t.index ['privacy'], name: 'by_community_privacy' + t.index ['slug'], name: 'index_better_together_communities_on_slug', unique: true + end + + create_table 'better_together_content_blocks', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'type', null: false + t.string 'identifier', limit: 100 + t.jsonb 'accessibility_attributes', default: {}, null: false + t.jsonb 'content_settings', default: {}, null: false + t.jsonb 'css_settings', default: {}, null: false + t.jsonb 'data_attributes', default: {}, null: false + t.jsonb 'html_attributes', default: {}, null: false + t.jsonb 'layout_settings', default: {}, null: false + t.jsonb 'media_settings', default: {}, null: false + end + + create_table 'better_together_content_page_blocks', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'page_id', null: false + t.uuid 'block_id', null: false + t.integer 'position', null: false + t.index ['block_id'], name: 'index_better_together_content_page_blocks_on_block_id' + t.index %w[page_id block_id position], name: 'content_page_blocks_on_page_block_and_position' + t.index %w[page_id block_id], name: 'content_page_blocks_on_page_and_block', unique: true + t.index ['page_id'], name: 'index_better_together_content_page_blocks_on_page_id' + end + + create_table 'better_together_conversation_participants', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'conversation_id', null: false + t.uuid 'person_id', null: false + t.index ['conversation_id'], name: 'idx_on_conversation_id_30b3b70bad' + t.index ['person_id'], name: 'index_better_together_conversation_participants_on_person_id' + end + + create_table 'better_together_conversations', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'title', null: false + t.uuid 'creator_id', null: false + t.index ['creator_id'], name: 'index_better_together_conversations_on_creator_id' + end + + create_table 'better_together_geography_continents', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.uuid 'community_id', null: false + t.string 'slug', null: false + t.index ['community_id'], name: 'by_geography_continent_community' + t.index ['identifier'], name: 'index_better_together_geography_continents_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_geography_continents_on_slug', unique: true + end + + create_table 'better_together_geography_countries', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.string 'iso_code', limit: 2, null: false + t.boolean 'protected', default: false, null: false + t.uuid 'community_id', null: false + t.string 'slug', null: false + t.index ['community_id'], name: 'by_geography_country_community' + t.index ['identifier'], name: 'index_better_together_geography_countries_on_identifier', unique: true + t.index ['iso_code'], name: 'index_better_together_geography_countries_on_iso_code', unique: true + t.index ['slug'], name: 'index_better_together_geography_countries_on_slug', unique: true + end + + create_table 'better_together_geography_country_continents', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'country_id' + t.uuid 'continent_id' + t.index ['continent_id'], name: 'country_continent_by_continent' + t.index %w[country_id continent_id], name: 'index_country_continents_on_country_and_continent', unique: true + t.index ['country_id'], name: 'country_continent_by_country' + end + + create_table 'better_together_geography_region_settlements', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.boolean 'protected', default: false, null: false + t.uuid 'region_id' + t.uuid 'settlement_id' + t.index ['region_id'], name: 'bt_region_settlement_by_region' + t.index ['settlement_id'], name: 'bt_region_settlement_by_settlement' + end + + create_table 'better_together_geography_regions', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.uuid 'community_id', null: false + t.uuid 'country_id' + t.uuid 'state_id' + t.string 'slug', null: false + t.string 'type', default: 'BetterTogether::Geography::Region', null: false + t.index ['community_id'], name: 'by_geography_region_community' + t.index ['country_id'], name: 'index_better_together_geography_regions_on_country_id' + t.index ['identifier'], name: 'index_better_together_geography_regions_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_geography_regions_on_slug', unique: true + t.index ['state_id'], name: 'index_better_together_geography_regions_on_state_id' + end + + create_table 'better_together_geography_settlements', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.uuid 'community_id', null: false + t.uuid 'country_id' + t.uuid 'state_id' + t.string 'slug', null: false + t.index ['community_id'], name: 'by_geography_settlement_community' + t.index ['country_id'], name: 'index_better_together_geography_settlements_on_country_id' + t.index ['identifier'], name: 'index_better_together_geography_settlements_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_geography_settlements_on_slug', unique: true + t.index ['state_id'], name: 'index_better_together_geography_settlements_on_state_id' + end + + create_table 'better_together_geography_states', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.string 'iso_code', limit: 5, null: false + t.boolean 'protected', default: false, null: false + t.uuid 'community_id', null: false + t.uuid 'country_id' + t.string 'slug', null: false + t.index ['community_id'], name: 'by_geography_state_community' + t.index ['country_id'], name: 'index_better_together_geography_states_on_country_id' + t.index ['identifier'], name: 'index_better_together_geography_states_on_identifier', unique: true + t.index ['iso_code'], name: 'index_better_together_geography_states_on_iso_code', unique: true + t.index ['slug'], name: 'index_better_together_geography_states_on_slug', unique: true + end + + create_table 'better_together_identifications', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.boolean 'active', null: false + t.string 'identity_type', null: false + t.uuid 'identity_id', null: false + t.string 'agent_type', null: false + t.uuid 'agent_id', null: false + t.index %w[active agent_type agent_id], name: 'active_identification', unique: true + t.index ['active'], name: 'by_active_state' + t.index %w[agent_type agent_id], name: 'by_agent' + t.index %w[identity_type identity_id agent_type agent_id], name: 'unique_identification', unique: true + t.index %w[identity_type identity_id], name: 'by_identity' + end + + create_table 'better_together_jwt_denylists', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'jti' + t.datetime 'exp' + t.index ['jti'], name: 'index_better_together_jwt_denylists_on_jti' + end + + create_table 'better_together_messages', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.text 'content', null: false + t.uuid 'sender_id', null: false + t.uuid 'conversation_id', null: false + t.index ['conversation_id'], name: 'index_better_together_messages_on_conversation_id' + t.index ['sender_id'], name: 'index_better_together_messages_on_sender_id' + end + + create_table 'better_together_navigation_areas', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.string 'slug', null: false + t.boolean 'visible', default: true, null: false + t.string 'name' + t.string 'style' + t.string 'navigable_type' + t.bigint 'navigable_id' + t.index ['identifier'], name: 'index_better_together_navigation_areas_on_identifier', unique: true + t.index %w[navigable_type navigable_id], name: 'by_navigable' + t.index ['slug'], name: 'index_better_together_navigation_areas_on_slug', unique: true + end + + create_table 'better_together_navigation_items', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.integer 'position', null: false + t.boolean 'protected', default: false, null: false + t.string 'slug', null: false + t.boolean 'visible', default: true, null: false + t.uuid 'navigation_area_id', null: false + t.uuid 'parent_id' + t.string 'url' + t.string 'icon' + t.string 'item_type', null: false + t.string 'linkable_type' + t.uuid 'linkable_id' + t.string 'route_name' + t.index ['identifier'], name: 'index_better_together_navigation_items_on_identifier', unique: true + t.index %w[linkable_type linkable_id], name: 'by_linkable' + t.index %w[navigation_area_id parent_id position], name: 'navigation_items_area_position', unique: true + t.index ['navigation_area_id'], name: 'index_better_together_navigation_items_on_navigation_area_id' + t.index ['parent_id'], name: 'by_nav_item_parent' + t.index ['slug'], name: 'index_better_together_navigation_items_on_slug', unique: true + end + + create_table 'better_together_pages', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.string 'slug', null: false + t.text 'meta_description' + t.string 'keywords' + t.datetime 'published_at' + t.string 'privacy', default: 'public', null: false + t.string 'layout' + t.string 'template' + t.index ['identifier'], name: 'index_better_together_pages_on_identifier', unique: true + t.index ['privacy'], name: 'by_page_privacy' + t.index ['published_at'], name: 'by_page_publication_date' + t.index ['slug'], name: 'index_better_together_pages_on_slug', unique: true + end + + create_table 'better_together_people', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.string 'slug', null: false + t.uuid 'community_id', null: false + t.jsonb 'preferences', default: {}, null: false + t.index ['community_id'], name: 'by_person_community' + t.index ['identifier'], name: 'index_better_together_people_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_people_on_slug', unique: true + end + + create_table 'better_together_person_community_memberships', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'member_id', null: false + t.uuid 'joinable_id', null: false + t.uuid 'role_id', null: false + t.index %w[joinable_id member_id role_id], name: 'unique_person_community_membership_member_role', + unique: true + t.index ['joinable_id'], name: 'person_community_membership_by_joinable' + t.index ['member_id'], name: 'person_community_membership_by_member' + t.index ['role_id'], name: 'person_community_membership_by_role' + end + + create_table 'better_together_person_platform_memberships', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'member_id', null: false + t.uuid 'joinable_id', null: false + t.uuid 'role_id', null: false + t.index %w[joinable_id member_id role_id], name: 'unique_person_platform_membership_member_role', unique: true + t.index ['joinable_id'], name: 'person_platform_membership_by_joinable' + t.index ['member_id'], name: 'person_platform_membership_by_member' + t.index ['role_id'], name: 'person_platform_membership_by_role' + end + + create_table 'better_together_platform_invitations', id: :uuid, default: lambda { # rubocop:todo Metrics/BlockLength + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'community_role_id', null: false + t.string 'invitee_email', null: false + t.uuid 'invitable_id', null: false + t.uuid 'invitee_id' + t.uuid 'inviter_id', null: false + t.uuid 'platform_role_id' + t.string 'status', limit: 20, null: false + t.string 'locale', limit: 5, default: 'en', null: false + t.string 'token', limit: 24, null: false + t.datetime 'valid_from', null: false + t.datetime 'valid_until' + t.datetime 'last_sent' + t.datetime 'accepted_at' + t.index ['community_role_id'], name: 'platform_invitations_by_community_role' + t.index %w[invitable_id status], name: 'index_platform_invitations_on_invitable_id_and_status' + t.index ['invitable_id'], name: 'platform_invitations_by_invitable' + t.index %w[invitee_email invitable_id], name: 'idx_on_invitee_email_invitable_id_5a7d642388', unique: true + t.index ['invitee_email'], name: 'index_pending_invitations_on_invitee_email', + where: "((status)::text = 'pending'::text)" + t.index ['invitee_email'], name: 'platform_invitations_by_invitee_email' + t.index ['invitee_id'], name: 'platform_invitations_by_invitee' + t.index ['inviter_id'], name: 'platform_invitations_by_inviter' + t.index ['locale'], name: 'platform_invitations_by_locale' + t.index ['platform_role_id'], name: 'platform_invitations_by_platform_role' + t.index ['status'], name: 'platform_invitations_by_status' + t.index ['token'], name: 'platform_invitations_by_token', unique: true + t.index ['valid_from'], name: 'platform_invitations_by_valid_from' + t.index ['valid_until'], name: 'platform_invitations_by_valid_until' + end + + create_table 'better_together_platforms', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'host', default: false, null: false + t.boolean 'protected', default: false, null: false + t.string 'privacy', limit: 50, default: 'public', null: false + t.string 'slug', null: false + t.uuid 'community_id' + t.string 'url', null: false + t.string 'time_zone', null: false + t.jsonb 'settings', default: {}, null: false + t.index ['community_id'], name: 'by_platform_community' + t.index ['host'], name: 'index_better_together_platforms_on_host', unique: true, where: '(host IS TRUE)' + t.index ['identifier'], name: 'index_better_together_platforms_on_identifier', unique: true + t.index ['privacy'], name: 'by_platform_privacy' + t.index ['slug'], name: 'index_better_together_platforms_on_slug', unique: true + t.index ['url'], name: 'index_better_together_platforms_on_url', unique: true + end + + create_table 'better_together_resource_permissions', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.integer 'position', null: false + t.string 'resource_type', null: false + t.string 'slug', null: false + t.string 'action', null: false + t.string 'target', null: false + t.index ['identifier'], name: 'index_better_together_resource_permissions_on_identifier', unique: true + t.index %w[resource_type position], name: 'index_resource_permissions_on_resource_type_and_position', + unique: true + t.index ['slug'], name: 'index_better_together_resource_permissions_on_slug', unique: true + end + + create_table 'better_together_role_resource_permissions', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'role_id', null: false + t.uuid 'resource_permission_id', null: false + t.index ['resource_permission_id'], name: 'role_resource_permissions_resource_permission' + t.index %w[role_id resource_permission_id], name: 'unique_role_resource_permission_index', unique: true + t.index ['role_id'], name: 'role_resource_permissions_role' + end + + create_table 'better_together_roles', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.integer 'position', null: false + t.string 'resource_type', null: false + t.string 'slug', null: false + t.index ['identifier'], name: 'index_better_together_roles_on_identifier', unique: true + t.index %w[resource_type position], name: 'index_roles_on_resource_type_and_position', unique: true + t.index ['slug'], name: 'index_better_together_roles_on_slug', unique: true + end + + create_table 'better_together_users', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'email', default: '', null: false + t.string 'encrypted_password', default: '', null: false + t.string 'reset_password_token' + t.datetime 'reset_password_sent_at' + t.datetime 'remember_created_at' + t.integer 'sign_in_count', default: 0, null: false + t.datetime 'current_sign_in_at' + t.datetime 'last_sign_in_at' + t.string 'current_sign_in_ip' + t.string 'last_sign_in_ip' + t.string 'confirmation_token' + t.datetime 'confirmed_at' + t.datetime 'confirmation_sent_at' + t.string 'unconfirmed_email' + t.integer 'failed_attempts', default: 0, null: false + t.string 'unlock_token' + t.datetime 'locked_at' + t.index ['confirmation_token'], name: 'index_better_together_users_on_confirmation_token', unique: true + t.index ['email'], name: 'index_better_together_users_on_email', unique: true + t.index ['reset_password_token'], name: 'index_better_together_users_on_reset_password_token', unique: true + t.index ['unlock_token'], name: 'index_better_together_users_on_unlock_token', unique: true + end + + create_table 'better_together_wizard_step_definitions', id: :uuid, default: lambda { + 'gen_random_uuid()' + }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.string 'slug', null: false + t.uuid 'wizard_id', null: false + t.string 'template' + t.string 'form_class' + t.string 'message', default: 'Please complete this next step.', null: false + t.integer 'step_number', null: false + t.index ['identifier'], name: 'index_better_together_wizard_step_definitions_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_wizard_step_definitions_on_slug', unique: true + t.index %w[wizard_id step_number], name: 'index_wizard_step_definitions_on_wizard_id_and_step_number', + unique: true + t.index ['wizard_id'], name: 'by_step_definition_wizard' + end + + create_table 'better_together_wizard_steps', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.uuid 'wizard_id', null: false + t.uuid 'wizard_step_definition_id', null: false + t.uuid 'creator_id' + t.string 'identifier', limit: 100, null: false + t.boolean 'completed', default: false + t.integer 'step_number', null: false + t.index ['creator_id'], name: 'by_step_creator' + t.index ['identifier'], name: 'by_step_identifier' + t.index %w[wizard_id identifier creator_id], name: 'index_unique_wizard_steps', unique: true, + where: '(completed IS FALSE)' + t.index %w[wizard_id step_number], name: 'index_wizard_steps_on_wizard_id_and_step_number' + t.index ['wizard_id'], name: 'by_step_wizard' + t.index ['wizard_step_definition_id'], name: 'by_step_wizard_step_definition' + end + + create_table 'better_together_wizards', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'identifier', limit: 100, null: false + t.boolean 'protected', default: false, null: false + t.string 'slug', null: false + t.integer 'max_completions', default: 0, null: false + t.integer 'current_completions', default: 0, null: false + t.datetime 'first_completed_at' + t.datetime 'last_completed_at' + t.text 'success_message', default: 'Thank you. You have successfully completed the wizard', null: false + t.string 'success_path', default: '/', null: false + t.index ['identifier'], name: 'index_better_together_wizards_on_identifier', unique: true + t.index ['slug'], name: 'index_better_together_wizards_on_slug', unique: true + end + + create_table 'friendly_id_slugs', force: :cascade do |t| + t.string 'slug', null: false + t.uuid 'sluggable_id', null: false + t.string 'sluggable_type', null: false + t.string 'scope' + t.integer 'lock_version', default: 0, null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'locale', null: false + t.index ['locale'], name: 'index_friendly_id_slugs_on_locale' + t.index %w[slug sluggable_type locale], name: 'index_friendly_id_slugs_on_slug_and_sluggable_type_and_locale' + t.index %w[slug sluggable_type scope locale], name: 'index_friendly_id_slugs_unique', unique: true + t.index %w[sluggable_type sluggable_id], name: 'by_sluggable' + end + + create_table 'mobility_string_translations', force: :cascade do |t| + t.string 'locale', null: false + t.string 'key', null: false + t.string 'value' + t.string 'translatable_type' + t.uuid 'translatable_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index %w[translatable_id translatable_type key], + name: 'index_mobility_string_translations_on_translatable_attribute' + t.index %w[translatable_id translatable_type locale key], + name: 'index_mobility_string_translations_on_keys', unique: true + t.index %w[translatable_type key value locale], name: 'index_mobility_string_translations_on_query_keys' + end + + create_table 'mobility_text_translations', force: :cascade do |t| + t.string 'locale', null: false + t.string 'key', null: false + t.text 'value' + t.string 'translatable_type' + t.uuid 'translatable_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index %w[translatable_id translatable_type key], + name: 'index_mobility_text_translations_on_translatable_attribute' + t.index %w[translatable_id translatable_type locale key], + name: 'index_mobility_text_translations_on_keys', unique: true + end + + create_table 'noticed_events', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.string 'type' + t.string 'record_type' + t.uuid 'record_id' + t.jsonb 'params' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.integer 'notifications_count' + t.index %w[record_type record_id], name: 'index_noticed_events_on_record' + end + + create_table 'noticed_notifications', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t| + t.string 'type' + t.uuid 'event_id', null: false + t.string 'recipient_type', null: false + t.uuid 'recipient_id', null: false + t.datetime 'read_at', precision: nil + t.datetime 'seen_at', precision: nil + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['event_id'], name: 'index_noticed_notifications_on_event_id' + t.index %w[recipient_type recipient_id], name: 'index_noticed_notifications_on_recipient' + end + + add_foreign_key 'active_storage_attachments', 'active_storage_blobs', column: 'blob_id' + add_foreign_key 'active_storage_variant_records', 'active_storage_blobs', column: 'blob_id' + add_foreign_key 'better_together_communities', 'better_together_people', column: 'creator_id' + add_foreign_key 'better_together_content_page_blocks', 'better_together_content_blocks', column: 'block_id' + add_foreign_key 'better_together_content_page_blocks', 'better_together_pages', column: 'page_id' + add_foreign_key 'better_together_conversation_participants', 'better_together_conversations', + column: 'conversation_id' + add_foreign_key 'better_together_conversation_participants', 'better_together_people', column: 'person_id' + add_foreign_key 'better_together_conversations', 'better_together_people', column: 'creator_id' + add_foreign_key 'better_together_geography_continents', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_geography_countries', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_geography_country_continents', 'better_together_geography_continents', + column: 'continent_id' + add_foreign_key 'better_together_geography_country_continents', 'better_together_geography_countries', + column: 'country_id' + add_foreign_key 'better_together_geography_region_settlements', 'better_together_geography_regions', + column: 'region_id' + add_foreign_key 'better_together_geography_region_settlements', 'better_together_geography_settlements', + column: 'settlement_id' + add_foreign_key 'better_together_geography_regions', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_geography_regions', 'better_together_geography_countries', column: 'country_id' + add_foreign_key 'better_together_geography_regions', 'better_together_geography_states', column: 'state_id' + add_foreign_key 'better_together_geography_settlements', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_geography_settlements', 'better_together_geography_countries', column: 'country_id' + add_foreign_key 'better_together_geography_settlements', 'better_together_geography_states', column: 'state_id' + add_foreign_key 'better_together_geography_states', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_geography_states', 'better_together_geography_countries', column: 'country_id' + add_foreign_key 'better_together_messages', 'better_together_conversations', column: 'conversation_id' + add_foreign_key 'better_together_messages', 'better_together_people', column: 'sender_id' + add_foreign_key 'better_together_navigation_items', 'better_together_navigation_areas', column: 'navigation_area_id' + add_foreign_key 'better_together_navigation_items', 'better_together_navigation_items', column: 'parent_id' + add_foreign_key 'better_together_people', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_person_community_memberships', 'better_together_communities', column: 'joinable_id' + add_foreign_key 'better_together_person_community_memberships', 'better_together_people', column: 'member_id' + add_foreign_key 'better_together_person_community_memberships', 'better_together_roles', column: 'role_id' + add_foreign_key 'better_together_person_platform_memberships', 'better_together_people', column: 'member_id' + add_foreign_key 'better_together_person_platform_memberships', 'better_together_platforms', column: 'joinable_id' + add_foreign_key 'better_together_person_platform_memberships', 'better_together_roles', column: 'role_id' + add_foreign_key 'better_together_platform_invitations', 'better_together_people', column: 'invitee_id' + add_foreign_key 'better_together_platform_invitations', 'better_together_people', column: 'inviter_id' + add_foreign_key 'better_together_platform_invitations', 'better_together_platforms', column: 'invitable_id' + add_foreign_key 'better_together_platform_invitations', 'better_together_roles', column: 'community_role_id' + add_foreign_key 'better_together_platform_invitations', 'better_together_roles', column: 'platform_role_id' + add_foreign_key 'better_together_platforms', 'better_together_communities', column: 'community_id' + add_foreign_key 'better_together_role_resource_permissions', 'better_together_resource_permissions', + column: 'resource_permission_id' + add_foreign_key 'better_together_role_resource_permissions', 'better_together_roles', column: 'role_id' + add_foreign_key 'better_together_wizard_step_definitions', 'better_together_wizards', column: 'wizard_id' + add_foreign_key 'better_together_wizard_steps', 'better_together_people', column: 'creator_id' + add_foreign_key 'better_together_wizard_steps', 'better_together_wizard_step_definitions', + column: 'wizard_step_definition_id' + add_foreign_key 'better_together_wizard_steps', 'better_together_wizards', column: 'wizard_id' end