Created
August 18, 2012 15:32
-
-
Save mislav/3387743 to your computer and use it in GitHub Desktop.
Raise error if "initialize" method name is misspelled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Public: Implementation of "Strike a match" algorithm for calculating | |
# similarity between strings. | |
# | |
# http://www.catalysoft.com/articles/StrikeAMatch.html | |
# | |
# Examples | |
# | |
# checker = StringSimilarityChecker.new('Quick brown fox') | |
# | |
# checker =~ 'quick brown ox' #=> true | |
# checker.similarity_index('quick brown ox') #=> 0.947 | |
# | |
# checker =~ 'quick frown pox' #=> true | |
# checker.similarity_index('quick frown pox') #=> 0.8 | |
# | |
# checker =~ 'quick lawn ducks' #=> false | |
# checker.similarity_index('quick lawn ducks') #=> 0.476 | |
class StringSimilarityChecker | |
def initialize base_string, similarity_treshold = 0.8 | |
@base_pairs = character_pairs base_string | |
@treshold = similarity_treshold | |
end | |
# Public: Check if similarity index with given string passes the treshold. | |
def similar_to? string | |
similarity_index(string) >= @treshold | |
end | |
alias =~ similar_to? | |
# Public: Calculate similarity index between given and base strings. | |
# | |
# Returns a Float between 0 and 1. | |
def similarity_index string | |
pairs = character_pairs string | |
shared = count_identical_pairs @base_pairs, pairs | |
(2 * shared).to_f / (@base_pairs.size + pairs.size) | |
end | |
SPACE = ' ' | |
# Internal: Break string into pairs of adjacent characters, excluding ones | |
# that contain spaces. | |
def character_pairs str | |
str = str.to_str.downcase | |
(0..(str.size-2)).map {|pos| str[pos,2] }.reject {|pair| pair.include? SPACE } | |
end | |
# Internal: Measure the intersection between two arrays of character pairs. | |
def count_identical_pairs pairs1, pairs2 | |
size, pairs2 = 0, pairs2.dup | |
pairs1.each do |pair| | |
if found = pairs2.index(pair) | |
size += 1 | |
pairs2.delete_at found | |
end | |
end | |
size | |
end | |
end | |
class Class | |
initializer_name = 'initialize' | |
initializer_spelling_checker = StringSimilarityChecker.new initializer_name | |
# Raise error if a new method is similar but not identical to "initialize". | |
# WARNING this is not something you should actually use in your apps. | |
define_method(:method_added) do |name| | |
name = name.to_s | |
if name != initializer_name and initializer_spelling_checker =~ name | |
raise "method name too similar to 'initialize': '#{name}'" | |
end | |
end | |
end | |
class ThisWorks | |
def initialize # properly spelled method | |
end | |
def init # valid method name | |
end | |
end | |
class ThisFails | |
def initializer # wrong name | |
end | |
end | |
class ThisAlsoFails | |
def initilize # spelling error | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment