Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions lib/phrase_identifier.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
# frozen_string_literal: true

class PhraseIdentifier
class Error < RuntimeError
end

def self.generate
phrase = Word.order(Arel.sql('RANDOM()')).take(3).pluck(:word).join('-') until unique?(phrase)
phrase
10.times do
phrase = Word.order(Arel.sql('RANDOM()')).take(3).pluck(:word).join('-')

# Uh-oh, no words found?
raise PhraseIdentifier::Error, 'Unable to generate a random phrase identifier' if phrase.blank?

return phrase if unique?(phrase)
end

# Hmmm we've tried 10 times, so raise an exception.
raise PhraseIdentifier::Error, 'Unable to generate a unique phrase identifier'
end

def self.unique?(phrase)
!phrase.nil? && Project.find_by(identifier: phrase).nil?
phrase.present? && Project.where(identifier: phrase).none?
end
end
7 changes: 7 additions & 0 deletions spec/factories/word.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

FactoryBot.define do
factory :word do
word { Faker::Verb.base }
end
end
53 changes: 53 additions & 0 deletions spec/lib/phrase_identifier_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require 'rails_helper'
require 'phrase_identifier'

RSpec.describe PhraseIdentifier do
describe '#generate' do
subject(:generate) { described_class.generate }

context 'when there are words in the database' do
let(:words) { %w[a b c] }
let(:phrase_regex) { /^[abc]-[abc]-[abc]$/ }

before do
Word.delete_all
words.each { |word| Word.new(word:).save! }
end

it { is_expected.to match phrase_regex }
end

context 'when there are no available combinations' do
let(:identifier) { create(:word).word }

before do
Word.delete_all
create(:project, identifier:)
end

it { expect { generate }.to raise_exception(PhraseIdentifier::Error) }
end

context 'when no words are in the database' do
before { Word.delete_all }

it { expect { generate }.to raise_exception(PhraseIdentifier::Error) }
end
end

describe '#unique?' do
subject { described_class.unique?(phrase) }

let(:phrase) { 'Hello? Is it me you\'re looking for?' }

it { is_expected.to be_truthy }

context 'when a project exists with the phrase as its identifier' do
before { create(:project, identifier: phrase) }

it { is_expected.to be_falsey }
end
end
end