diff --git a/Gemfile b/Gemfile index f01ca559f..9e00b3024 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,8 @@ gem 'turbo-rails' group :development, :test do gem 'dotenv-rails' + gem 'factory_bot_rails' + gem 'faker' gem 'rspec-rails' gem 'rubocop' end diff --git a/Gemfile.lock b/Gemfile.lock index 6624e9608..015db9226 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,6 +72,13 @@ GEM dotenv (= 2.7.6) railties (>= 3.2) erubi (1.10.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faker (2.19.0) + i18n (>= 1.6, < 2) globalid (1.0.0) activesupport (>= 5.0) i18n (1.8.11) @@ -96,6 +103,8 @@ GEM nokogiri (1.12.5) mini_portile2 (~> 2.6.1) racc (~> 1.4) + nokogiri (1.12.5-x86_64-linux) + racc (~> 1.4) parallel (1.21.0) parser (3.0.3.2) ast (~> 2.4.1) @@ -197,6 +206,8 @@ PLATFORMS DEPENDENCIES bootsnap dotenv-rails + factory_bot_rails + faker importmap-rails jbuilder pg (~> 1.1) diff --git a/app/models/project.rb b/app/models/project.rb index 038537e7b..2ae323033 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,3 +1,15 @@ +require 'phrase_identifier' + class Project < ApplicationRecord + before_validation :check_unique_not_null, on: :create + validates :identifier, presence: true, uniqueness: true has_many :components, dependent: :destroy -end + + private + def check_unique_not_null + self.identifier ||= PhraseIdentifier.generate + while !Project.find_by(identifier: self.identifier).nil? + self.identifier = PhraseIdentifier.generate + end + end +end \ No newline at end of file diff --git a/db/migrate/20220111141057_make_project_identifier_non_null.rb b/db/migrate/20220111141057_make_project_identifier_non_null.rb new file mode 100644 index 000000000..e0360f7df --- /dev/null +++ b/db/migrate/20220111141057_make_project_identifier_non_null.rb @@ -0,0 +1,5 @@ +class MakeProjectIdentifierNonNull < ActiveRecord::Migration[7.0] + def change + change_column_null(:projects, :identifier, false) + end +end diff --git a/db/schema.rb b/db/schema.rb index 3fd86102c..43e38b3f7 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.define(version: 2021_12_21_135519) do +ActiveRecord::Schema.define(version: 2022_01_11_141057) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -29,7 +29,7 @@ create_table "projects", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "user_id" t.string "name" - t.string "identifier" + t.string "identifier", null: false t.string "project_type", default: "python", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false diff --git a/spec/factories/project.rb b/spec/factories/project.rb new file mode 100644 index 000000000..053055160 --- /dev/null +++ b/spec/factories/project.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :project do + user_id { rand( 10 ** 10 ) } + name { Faker::Book.title } + identifier { Faker::Verb.base+'-'+Faker::Verb.base+'-'+Faker::Verb.base } + project_type { %w[python, html].sample } + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 5df403ad8..72785e11e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1,7 +1,22 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe Project, type: :model do describe 'associations' do it { is_expected.to have_many(:components) } end + + describe 'identifier not nil' do + subject { FactoryBot.build(:project) } + it { is_expected.not_to allow_value(nil).for(:identifier) } + end + + describe 'identifier unique' do + it do + project1 = FactoryBot.create(:project) + project2 = FactoryBot.build(:project, identifier: project1.identifier) + expect { project2.valid? }.to change { project2.identifier } + end + end end