module UsernameSuggester
class Suggester
attr_reader :first_name, :last_name
# A Suggester class to suggest user_names
#
# ==== Parameters
#
# * :first_name - Required.
# * :last_name - Required.
# * :options - See UsernameSuggester::SuggestionsFor
#
def initialize(first_name, last_name)
raise Error, "first_name or last_name has not been specified" if first_name.nil? || last_name.nil?
@first_name = first_name.downcase.gsub(/[^\w]/, '')
@last_name = last_name.downcase.gsub(/[^\w]/, '')
end
# Generates the combinations without the knowledge of what names are available
def name_combinations
@name_combinations ||= [
"#{first_name}",
"#{last_name}",
"#{first_name[0]}#{last_name}",
"#{first_name}#{last_name[0]}",
"#{first_name}#{last_name}",
"#{last_name[0]}#{first_name}",
"#{last_name}#{first_name[0]}",
"#{last_name}#{first_name}"
].uniq.reject { |s| s.blank? }
end
# Generates suggestions and making sure they are not in unavailable_suggestions
def suggest(options)
candidates_to_exclude = options[:exclude]
validation_block = options[:validate]
number_of_suggestions = options[:num_suggestions]
results = []
candidates = name_combinations.clone
while results.size < number_of_suggestions && !candidates.blank?
candidate = candidates.shift
if validation_block.try(:call, candidate)
# Don't add the candidate to result
elsif candidates_to_exclude.include? candidate
candidates << find_extended_candidate(candidate, candidates_to_exclude)
else
results << candidate
end
end
results
end
private
# Generates a candidate with "candidate" which is not included in unavailable_set
def find_extended_candidate(candidate, candidates_to_exclude)
i = 1
i+=rand(10) while candidates_to_exclude.include? "#{candidate}#{i}"
"#{candidate}#{i}"
end
end
end