Skip to content

Instantly share code, notes, and snippets.

@punund
Created June 19, 2011 15:45
Show Gist options
  • Save punund/1034426 to your computer and use it in GitHub Desktop.
Save punund/1034426 to your computer and use it in GitHub Desktop.
Generation of alphanumeric person handle
#
# This automatically creates a "handle" upon creation of person's record.
#
# "John Doe"'s handle shall look like "DO<x>J", where <x> is a minimal necessary number of digits,
# so we have to look up the existing handles first. We exclude zeros (to avoid confusion with Os)
# and ones (to exclude jealousy "to be the first"), so we conveniently employ octal digits and add
# two subsequently. We also have to do the best effort to normalize last names (drop diacritics,
# honorifics, Celtic and Dutch name prefixes, sr/jr suffixes, etc. to maximize variance.
#
# See this in action at http://dia-x.info/authors
#
class Author < ActiveRecord::Base
has_and_belongs_to_many :diagrams
validates_presence_of :name
validates_format_of :name, with: /^(.+)\s+(\S+)$/,
message: 'must consist of given names and family name.'
cattr_reader :per_page
@@per_page = 99
before_save :generate_code
attr_accessible :name
#########################################
protected
#########################################
def generate_code
return unless self.code.blank?
nname = self.name.mb_chars.normalize(:kd).gsub(/[^\x20-\x7F]/,'').upcase.to_s
nname.gsub! /\(.*\)/, '' # no parens
nname.gsub! / MC/, ' ' # no McSomeone
nname.gsub! / O\'/, ' ' # no O'Anybody
nname.gsub! / VAN (DER )?/, ' ' # Vanderbilt is OK, van der Bilt is not
nname.gsub! / SR\.?$| JR\.?$/, '' # no sr or jr
nname.strip!
nname =~ /^(.+)\s+(\S+)$/
names, family = $1[0,1], $2[0,2]
@others = Author
.where(:code ^ nil)
.where(:code =~ family + '%' + names)
while true
trycode = family + random_code + names
unless @others.find {|i| i.code == trycode}
self.code = trycode
# logger.info "*** #{trycode} ***"
break
end
end
end
def random_code
digit8 = ''
limit = @others.size.to_s(8).size # cheap logarithm(8)
limit.times do
digit8 += (2 + rand(8)).to_s
end
return digit8
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment