Skip to content

Instantly share code, notes, and snippets.

@drhuffman12
Created July 9, 2020 23:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drhuffman12/75004ed6a3914f8e46319c9f6cd8c3f1 to your computer and use it in GitHub Desktop.
Save drhuffman12/75004ed6a3914f8e46319c9f6cd8c3f1 to your computer and use it in GitHub Desktop.
Ruby/SQL code to generate new unique incremented keys (e.g. usernames)
# example app code should guarantee a unique, sequenced username:
def calc_prefix(user, fmaxi = 7, lmaxi = 0)
# e.g.: extract users's first and last name (or use the email example or etc)
first_name = user.first_name
last_name = user.last_name
# now, force to lowercase and only (ascii? unicode?) letters and numbers
# first_name = first_name.downcase.gsub(/[^0-9a-z ]/i, '') # for ascii only
first_name = first_name.downcase.gsub(/[^\p{Alnum} -]/, '') # for unicode also
# last_name = last_name.downcase.gsub(/[^0-9a-z ]/i, '') # for ascii only
last_name = last_name.downcase.gsub(/[^\p{Alnum} -]/, '') # for unicode also
# and return like 'first.l' ...
# NOTE: We will limit to [0..fmaxi] chars for first name and likewise for last name
return "#{first_name[0..(fmaxi)]}.#{last_name[0..(lmaxi)]} # e.g.: "john.s"
end
def highest_count_match_with_or_with_count_suffix(prefix)
prefix_safer_sql = prefix.gsub('.','\.') # just a '.' means any char, so we must prefix with '\'
usernames = User.where("username REGEXP /^#{prefix_safer_sql}((\.[0-9]+))*$/gm").pluck(:username) #=> ["john.s", "john.s.0", "john.s.1", "john.s.2", "john.s.3", "john.s.4", "john.s.45", "john.s.456", "john.s.476865"]
numbers = usernames.map{|un| (un.split('.')[2] || '').to_i} #=> [0, 0, 1, 2, 3, 4, 45, 456, 476865]
numbers.max
end
def new_username(user, fmaxi = 7, lmaxi = 0)
prefix = calc_prefix(user, fmaxi, lmaxi)
highest_count = highest_count_match_with_or_with_count_suffix(prefix)
"#{prefix}.#{highest_count + 1}
end
# ...
username = new_username(user, fmaxi, lmaxi)
# test variables for the first-name-last-initial prefix matcher would be something like:
all_usernames = %w[
johnAs
john.s
john.s.0
john.s.1
john.s.2
john.s.3
john.s.4
john.s.45
john.s.456
john.s.476865
abcjohn.s.4
abcjohn.s.4xyz
]
expected_matches = %w[
john.s
john.s.0
john.s.1
john.s.2
john.s.3
john.s.4
john.s.45
john.s.456
john.s.476865
]
expected_last_count = 476865
expected_next_count = 476866
expected_username = "john.s.476866"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment