aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael França <rafaelmfranca@gmail.com>2018-05-01 15:07:04 -0400
committerGitHub <noreply@github.com>2018-05-01 15:07:04 -0400
commit5175f5bf786439cd85237ed924f6c2dc6214851b (patch)
tree33ec5c140b3c0d6481c93674a0f0a1c7b4c27455
parent5e5d53a2a3fcd1f3341f7aea17f74891339b32f2 (diff)
parent52a41974c2de62af9ad5950be9a7ee21484a7b27 (diff)
downloadrails-5175f5bf786439cd85237ed924f6c2dc6214851b.tar.gz
rails-5175f5bf786439cd85237ed924f6c2dc6214851b.tar.bz2
rails-5175f5bf786439cd85237ed924f6c2dc6214851b.zip
Merge pull request #32781 from utilum/retry_did_you_mean
Partly revert #32289 to provide Rails' custom fallback in case did_you_mean is not available
-rw-r--r--railties/lib/rails/command/spellchecker.rb51
1 files changed, 49 insertions, 2 deletions
diff --git a/railties/lib/rails/command/spellchecker.rb b/railties/lib/rails/command/spellchecker.rb
index 154358cd45..04485097fa 100644
--- a/railties/lib/rails/command/spellchecker.rb
+++ b/railties/lib/rails/command/spellchecker.rb
@@ -3,8 +3,55 @@
module Rails
module Command
module Spellchecker # :nodoc:
- def self.suggest(word, from:)
- DidYouMean::SpellChecker.new(dictionary: from.map(&:to_s)).correct(word).first
+ class << self
+ def suggest(word, from:)
+ if defined?(DidYouMean::SpellChecker)
+ DidYouMean::SpellChecker.new(dictionary: from.map(&:to_s)).correct(word).first
+ else
+ from.sort_by { |w| levenshtein_distance(word, w) }.first
+ end
+ end
+
+ private
+
+ # This code is based directly on the Text gem implementation.
+ # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
+ #
+ # Returns a value representing the "cost" of transforming str1 into str2.
+ def levenshtein_distance(str1, str2) # :doc:
+ s = str1
+ t = str2
+ n = s.length
+ m = t.length
+
+ return m if (0 == n)
+ return n if (0 == m)
+
+ d = (0..m).to_a
+ x = nil
+
+ # avoid duplicating an enumerable object in the loop
+ str2_codepoint_enumerable = str2.each_codepoint
+
+ str1.each_codepoint.with_index do |char1, i|
+ e = i + 1
+
+ str2_codepoint_enumerable.with_index do |char2, j|
+ cost = (char1 == char2) ? 0 : 1
+ x = [
+ d[j + 1] + 1, # insertion
+ e + 1, # deletion
+ d[j] + cost # substitution
+ ].min
+ d[j] = e
+ e = x
+ end
+
+ d[m] = x
+ end
+
+ x
+ end
end
end
end