Sha256: de934d2ba7cc941a1c803f0daf9de9ce1b11c10efa77908f6e9851516bab1efa

Contents?: true

Size: 1.4 KB

Versions: 1

Compression:

Stored size: 1.4 KB

Contents

require "did_you_mean/levenshtein"
require "did_you_mean/jaro_winkler"

module DidYouMean
  module SpellCheckable
    AT    = "@".freeze
    EMPTY = "".freeze

    def corrections
      @corrections ||= candidates.flat_map do |input, candidates|
        input     = normalize(input)
        threshold = input.length > 3 ? 0.834 : 0.77

        seed = candidates.select {|candidate| JaroWinkler.distance(normalize(candidate), input) >= threshold }
          .sort_by! {|candidate| JaroWinkler.distance(candidate.to_s, input) }
          .reverse!

        # Correct mistypes
        threshold   = (input.length * 0.25).ceil
        corrections = seed.select {|c| Levenshtein.distance(normalize(c), input) <= threshold }

        # Correct misspells
        if corrections.empty?
          corrections = seed.select do |candidate|
            candidate = normalize(candidate)
            length    = input.length < candidate.length ? input.length : candidate.length

            Levenshtein.distance(candidate, input) < length
          end.first(1)
        end

        corrections
      end
    end

    def candidates
      raise NotImplementedError
    end

    private

    def normalize(str_or_symbol) #:nodoc:
      str = if str_or_symbol.is_a?(String)
              str_or_symbol.dup
            else
              str_or_symbol.to_s
            end

      str.downcase!
      str.tr!(AT, EMPTY)
      str
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
did_you_mean-1.0.0.beta2 lib/did_you_mean/spell_checkable.rb