From ef8c3cfe7ff6e61147711f74b60eda34acce54c5 Mon Sep 17 00:00:00 2001 From: Alex Turchyn Date: Thu, 21 Sep 2023 00:23:38 +0300 Subject: [PATCH] add folders migration --- app/models/account.rb | 9 +++++ app/models/template.rb | 12 ++++++ app/models/template_folder.rb | 34 ++++++++++++++++ .../20230920195319_create_template_folders.rb | 15 +++++++ ...230920202947_add_folder_id_to_templates.rb | 40 +++++++++++++++++++ db/schema.rb | 18 ++++++++- lib/ability.rb | 1 + spec/system/dashboard_spec.rb | 2 +- 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 app/models/template_folder.rb create mode 100644 db/migrate/20230920195319_create_template_folders.rb create mode 100644 db/migrate/20230920202947_add_folder_id_to_templates.rb diff --git a/app/models/account.rb b/app/models/account.rb index d06f1421..bec71f3e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -16,6 +16,9 @@ class Account < ApplicationRecord has_many :encrypted_configs, dependent: :destroy has_many :account_configs, dependent: :destroy has_many :templates, dependent: :destroy + has_many :template_folders, dependent: :destroy + has_one :default_folder, -> { where(name: TemplateFolder::DEFAULT_NAME) }, + class_name: 'TemplateFolder', dependent: :destroy, inverse_of: :account has_many :submissions, through: :templates has_many :submitters, through: :submissions has_many :active_users, -> { active }, dependent: :destroy, @@ -23,4 +26,10 @@ class Account < ApplicationRecord attribute :timezone, :string, default: 'UTC' attribute :locale, :string, default: 'en-US' + + def default_folder + super || template_folders.new(name: TemplateFolder::DEFAULT_NAME, + author_id: users.minimum(:id)) + .tap(&:save!) + end end diff --git a/app/models/template.rb b/app/models/template.rb index 47d32483..3ef60fa4 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -16,23 +16,29 @@ # updated_at :datetime not null # account_id :bigint not null # author_id :bigint not null +# folder_id :bigint not null # # Indexes # # index_templates_on_account_id (account_id) # index_templates_on_author_id (author_id) +# index_templates_on_folder_id (folder_id) # index_templates_on_slug (slug) UNIQUE # # Foreign Keys # # fk_rails_... (account_id => accounts.id) # fk_rails_... (author_id => users.id) +# fk_rails_... (folder_id => template_folders.id) # class Template < ApplicationRecord DEFAULT_SUBMITTER_NAME = 'First Submitter' belongs_to :author, class_name: 'User' belongs_to :account + belongs_to :folder, class_name: 'TemplateFolder' + + before_validation :maybe_set_default_folder, on: :create attribute :fields, :string, default: -> { [] } attribute :schema, :string, default: -> { [] } @@ -52,4 +58,10 @@ class Template < ApplicationRecord has_many :submissions, dependent: :destroy scope :active, -> { where(deleted_at: nil) } + + private + + def maybe_set_default_folder + self.folder ||= account.default_folder + end end diff --git a/app/models/template_folder.rb b/app/models/template_folder.rb new file mode 100644 index 00000000..e7fa4e84 --- /dev/null +++ b/app/models/template_folder.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: template_folders +# +# id :bigint not null, primary key +# deleted_at :datetime +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# account_id :bigint not null +# author_id :bigint not null +# +# Indexes +# +# index_template_folders_on_account_id (account_id) +# index_template_folders_on_author_id (author_id) +# +# Foreign Keys +# +# fk_rails_... (account_id => accounts.id) +# fk_rails_... (author_id => users.id) +# +class TemplateFolder < ApplicationRecord + DEFAULT_NAME = 'Default' + + belongs_to :author, class_name: 'User' + belongs_to :account + + has_many :templates, dependent: :destroy + + scope :active, -> { where(deleted_at: nil) } +end diff --git a/db/migrate/20230920195319_create_template_folders.rb b/db/migrate/20230920195319_create_template_folders.rb new file mode 100644 index 00000000..5fde9660 --- /dev/null +++ b/db/migrate/20230920195319_create_template_folders.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class CreateTemplateFolders < ActiveRecord::Migration[7.0] + def change + create_table :template_folders do |t| + t.string :name, null: false + + t.references :author, null: false, foreign_key: { to_table: :users }, index: true + t.references :account, null: false, foreign_key: true, index: true + + t.datetime :deleted_at + t.timestamps + end + end +end diff --git a/db/migrate/20230920202947_add_folder_id_to_templates.rb b/db/migrate/20230920202947_add_folder_id_to_templates.rb new file mode 100644 index 00000000..370b25c4 --- /dev/null +++ b/db/migrate/20230920202947_add_folder_id_to_templates.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class AddFolderIdToTemplates < ActiveRecord::Migration[7.0] + class MigrationTemplateFolder < ApplicationRecord + self.table_name = 'template_folders' + end + + class MigrationAccount < ApplicationRecord + self.table_name = 'accounts' + end + + class MigrationTemplate < ApplicationRecord + self.table_name = 'templates' + end + + class MigrationUser < ApplicationRecord + self.table_name = 'users' + end + + def up + add_reference :templates, :folder, foreign_key: { to_table: :template_folders }, index: true, null: true + + MigrationAccount.all.pluck(:id).each do |account_id| + author_id = MigrationUser.where(account_id:).minimum(:id) + + next if author_id.blank? + + folder = MigrationTemplateFolder.create_with(author_id:) + .find_or_create_by(name: 'Default', account_id:) + + MigrationTemplate.where(account_id:).update_all(folder_id: folder.id) + end + + change_column_null :templates, :folder_id, false + end + + def down + remove_column :templates, :folder_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 95db88d8..1062ba01 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.0].define(version: 2023_09_15_200635) do +ActiveRecord::Schema[7.0].define(version: 2023_09_20_202947) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -138,6 +138,17 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_15_200635) do t.index ["submission_id"], name: "index_submitters_on_submission_id" end + create_table "template_folders", force: :cascade do |t| + t.string "name", null: false + t.bigint "author_id", null: false + t.bigint "account_id", null: false + t.datetime "deleted_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id"], name: "index_template_folders_on_account_id" + t.index ["author_id"], name: "index_template_folders_on_author_id" + end + create_table "templates", force: :cascade do |t| t.string "slug", null: false t.string "name", null: false @@ -150,8 +161,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_15_200635) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.text "source", null: false + t.bigint "folder_id", null: false t.index ["account_id"], name: "index_templates_on_account_id" t.index ["author_id"], name: "index_templates_on_author_id" + t.index ["folder_id"], name: "index_templates_on_folder_id" t.index ["slug"], name: "index_templates_on_slug", unique: true end @@ -198,7 +211,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_15_200635) do add_foreign_key "submissions", "templates" add_foreign_key "submissions", "users", column: "created_by_user_id" add_foreign_key "submitters", "submissions" + add_foreign_key "template_folders", "accounts" + add_foreign_key "template_folders", "users", column: "author_id" add_foreign_key "templates", "accounts" + add_foreign_key "templates", "template_folders", column: "folder_id" add_foreign_key "templates", "users", column: "author_id" add_foreign_key "users", "accounts" end diff --git a/lib/ability.rb b/lib/ability.rb index eeb4acdc..3958861c 100644 --- a/lib/ability.rb +++ b/lib/ability.rb @@ -5,6 +5,7 @@ class Ability def initialize(user) can :manage, Template, account_id: user.account_id + can :manage, TemplateFolder, account_id: user.account_id can :manage, Submission, template: { account_id: user.account_id } can :manage, Submitter, template: { account_id: user.account_id } can :manage, User, account_id: user.account_id diff --git a/spec/system/dashboard_spec.rb b/spec/system/dashboard_spec.rb index 9ca98d3f..23198a50 100644 --- a/spec/system/dashboard_spec.rb +++ b/spec/system/dashboard_spec.rb @@ -23,7 +23,7 @@ RSpec.describe 'Dashboard Page' do context 'when there are templates' do let!(:authors) { create_list(:user, 5, account:) } let!(:templates) { authors.map { |author| create(:template, account:, author:) } } - let!(:other_template) { create(:template) } + let!(:other_template) { create(:template, account: create(:user).account) } before do visit root_path