Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent null or duplicate phrase identifiers for projects being inserted into the database #7

2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -197,6 +206,8 @@ PLATFORMS
DEPENDENCIES
bootsnap
dotenv-rails
factory_bot_rails
faker
importmap-rails
jbuilder
pg (~> 1.1)
Expand Down
14 changes: 13 additions & 1 deletion app/models/project.rb
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions db/migrate/20220111141057_make_project_identifier_non_null.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class MakeProjectIdentifierNonNull < ActiveRecord::Migration[7.0]
def change
change_column_null(:projects, :identifier, false)
end
end
4 changes: 2 additions & 2 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions spec/factories/project.rb
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions spec/models/project_spec.rb
Original file line number Diff line number Diff line change
@@ -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