mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-02 13:12:13 +08:00
Merge pull request #2928 from okriuchykhin/ok_SCI_5126
Create database structure for project folders [SCI-5126]
This commit is contained in:
commit
8566d56b68
7 changed files with 210 additions and 2 deletions
|
@ -30,6 +30,7 @@ class Project < ApplicationRecord
|
|||
class_name: 'User',
|
||||
optional: true
|
||||
belongs_to :team, inverse_of: :projects, touch: true
|
||||
belongs_to :project_folder, inverse_of: :projects, optional: true
|
||||
has_many :user_projects, inverse_of: :project
|
||||
has_many :users, through: :user_projects
|
||||
has_many :experiments, inverse_of: :project
|
||||
|
|
26
app/models/project_folder.rb
Normal file
26
app/models/project_folder.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ProjectFolder < ApplicationRecord
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
validates :name,
|
||||
length: { minimum: Constants::NAME_MIN_LENGTH,
|
||||
maximum: Constants::NAME_MAX_LENGTH },
|
||||
uniqueness: { scope: :team_id, case_sensitive: false }
|
||||
|
||||
before_validation :inherit_team_from_parent_folder, if: -> { parent_folder.present? }
|
||||
|
||||
belongs_to :team, inverse_of: :project_folders, touch: true
|
||||
belongs_to :parent_folder, class_name: 'ProjectFolder', optional: true
|
||||
has_many :projects, inverse_of: :project_folder, dependent: :nullify
|
||||
has_many :project_folders, foreign_key: 'parent_folder_id', inverse_of: :parent_folder, dependent: :destroy
|
||||
|
||||
scope :top_level, -> { where(parent_folder: nil) }
|
||||
|
||||
private
|
||||
|
||||
def inherit_team_from_parent_folder
|
||||
self.team = parent_folder.team
|
||||
end
|
||||
end
|
|
@ -31,6 +31,7 @@ class Team < ApplicationRecord
|
|||
has_many :user_teams, inverse_of: :team, dependent: :destroy
|
||||
has_many :users, through: :user_teams
|
||||
has_many :projects, inverse_of: :team
|
||||
has_many :project_folders, inverse_of: :team, dependent: :destroy
|
||||
has_many :protocols, inverse_of: :team, dependent: :destroy
|
||||
has_many :protocol_keywords, inverse_of: :team, dependent: :destroy
|
||||
has_many :tiny_mce_assets, inverse_of: :team, dependent: :destroy
|
||||
|
|
26
db/migrate/20201028103608_create_project_folders.rb
Normal file
26
db/migrate/20201028103608_create_project_folders.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateProjectFolders < ActiveRecord::Migration[6.0]
|
||||
include DatabaseHelper
|
||||
|
||||
def up
|
||||
create_table :project_folders do |t|
|
||||
t.string :name, null: false
|
||||
t.references :team, index: true, null: false, foreign_key: true
|
||||
t.references :parent_folder, index: true, foreign_key: { to_table: :project_folders }, null: true
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_reference :projects, :project_folder, index: true, foreign_key: true
|
||||
|
||||
add_gin_index_without_tags :project_folders, :name
|
||||
end
|
||||
|
||||
def down
|
||||
remove_index :project_folders, name: :index_project_folders_on_name
|
||||
|
||||
remove_reference :projects, :project_folder, index: true, foreign_key: true
|
||||
|
||||
drop_table :project_folders
|
||||
end
|
||||
end
|
106
db/structure.sql
106
db/structure.sql
|
@ -985,6 +985,39 @@ CREATE SEQUENCE public.oauth_applications_id_seq
|
|||
ALTER SEQUENCE public.oauth_applications_id_seq OWNED BY public.oauth_applications.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.project_folders (
|
||||
id bigint NOT NULL,
|
||||
name character varying NOT NULL,
|
||||
team_id bigint NOT NULL,
|
||||
parent_folder_id bigint,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.project_folders_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.project_folders_id_seq OWNED BY public.project_folders.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: projects; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -1006,7 +1039,8 @@ CREATE TABLE public.projects (
|
|||
restored_on timestamp without time zone,
|
||||
experiments_order character varying,
|
||||
template boolean,
|
||||
demo boolean DEFAULT false NOT NULL
|
||||
demo boolean DEFAULT false NOT NULL,
|
||||
project_folder_id bigint
|
||||
);
|
||||
|
||||
|
||||
|
@ -2947,6 +2981,13 @@ ALTER TABLE ONLY public.oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval(
|
|||
ALTER TABLE ONLY public.oauth_applications ALTER COLUMN id SET DEFAULT nextval('public.oauth_applications_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.project_folders ALTER COLUMN id SET DEFAULT nextval('public.project_folders_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: projects id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -3504,6 +3545,14 @@ ALTER TABLE ONLY public.oauth_applications
|
|||
ADD CONSTRAINT oauth_applications_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders project_folders_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.project_folders
|
||||
ADD CONSTRAINT project_folders_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: projects projects_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -4452,6 +4501,27 @@ CREATE INDEX index_on_repository_checklist_item_id ON public.repository_checklis
|
|||
CREATE INDEX index_on_repository_checklist_value_id ON public.repository_checklist_items_values USING btree (repository_checklist_value_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_project_folders_on_name; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_project_folders_on_name ON public.project_folders USING gin (public.trim_html_tags((name)::text) public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_project_folders_on_parent_folder_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_project_folders_on_parent_folder_id ON public.project_folders USING btree (parent_folder_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_project_folders_on_team_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_project_folders_on_team_id ON public.project_folders USING btree (team_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_projects_on_archived_by_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -4480,6 +4550,13 @@ CREATE INDEX index_projects_on_last_modified_by_id ON public.projects USING btre
|
|||
CREATE INDEX index_projects_on_name ON public.projects USING gin (public.trim_html_tags((name)::text) public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_projects_on_project_folder_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_projects_on_project_folder_id ON public.projects USING btree (project_folder_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_projects_on_restored_by_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -5617,6 +5694,14 @@ ALTER TABLE ONLY public.report_elements
|
|||
ADD CONSTRAINT fk_rails_0510000a52 FOREIGN KEY (table_id) REFERENCES public.tables(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders fk_rails_05fe6e31fe; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.project_folders
|
||||
ADD CONSTRAINT fk_rails_05fe6e31fe FOREIGN KEY (parent_folder_id) REFERENCES public.project_folders(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: assets fk_rails_0916329f9e; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -6025,6 +6110,14 @@ ALTER TABLE ONLY public.repository_status_items
|
|||
ADD CONSTRAINT fk_rails_74e5e4cacc FOREIGN KEY (repository_column_id) REFERENCES public.repository_columns(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: project_folders fk_rails_795296de66; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.project_folders
|
||||
ADD CONSTRAINT fk_rails_795296de66 FOREIGN KEY (team_id) REFERENCES public.teams(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: results fk_rails_79fcaa8e37; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -6753,6 +6846,14 @@ ALTER TABLE ONLY public.team_repositories
|
|||
ADD CONSTRAINT fk_rails_f99472b670 FOREIGN KEY (team_id) REFERENCES public.teams(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: projects fk_rails_fbf93d1a3d; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.projects
|
||||
ADD CONSTRAINT fk_rails_fbf93d1a3d FOREIGN KEY (project_folder_id) REFERENCES public.project_folders(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: my_modules fk_rails_fd094f363d; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -6960,6 +7061,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20200713142353'),
|
||||
('20200714082503'),
|
||||
('20200826143431'),
|
||||
('20200909121441');
|
||||
('20200909121441'),
|
||||
('20201028103608');
|
||||
|
||||
|
||||
|
|
8
spec/factories/project_folders.rb
Normal file
8
spec/factories/project_folders.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :project_folder do
|
||||
sequence(:name) { |n| "My projects folder (#{n})" }
|
||||
team { create :team }
|
||||
end
|
||||
end
|
44
spec/models/project_folder_spec.rb
Normal file
44
spec/models/project_folder_spec.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ProjectFolder, type: :model do
|
||||
let(:project_folder) { build :project_folder }
|
||||
|
||||
it 'is valid' do
|
||||
expect(project_folder).to be_valid
|
||||
end
|
||||
|
||||
it 'should be of class ProjectFolder' do
|
||||
expect(subject.class).to eq ProjectFolder
|
||||
end
|
||||
|
||||
describe 'Database table' do
|
||||
it { should have_db_column :id }
|
||||
it { should have_db_column :name }
|
||||
it { should have_db_column :team_id }
|
||||
it { should have_db_column :parent_folder_id }
|
||||
it { should have_db_column :created_at }
|
||||
it { should have_db_column :updated_at }
|
||||
end
|
||||
|
||||
describe 'Relations' do
|
||||
it { should belong_to(:team) }
|
||||
it { should belong_to(:parent_folder).class_name('ProjectFolder').optional }
|
||||
it { should have_many :projects }
|
||||
it { should have_many :project_folders }
|
||||
end
|
||||
|
||||
describe 'Validations' do
|
||||
describe '#name' do
|
||||
it do
|
||||
is_expected.to(validate_length_of(:name)
|
||||
.is_at_least(Constants::NAME_MIN_LENGTH)
|
||||
.is_at_most(Constants::NAME_MAX_LENGTH))
|
||||
end
|
||||
it do
|
||||
expect(project_folder).to validate_uniqueness_of(:name).scoped_to(:team_id).case_insensitive
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue