require "spec_helper"

describe Fuzzily::Model do
  subject do
    Class.new(ActiveRecord::Base).tap do |model|
      model.table_name = :trigrams

      def model.name ; "MyModel" ; end
    end
  end

  before(:each) { prepare_trigrams_table }

  it "can be included into an ActiveRecord model" do
    subject.send(:include, described_class)
  end

  it "can be included twice" do
    subject.send(:include, described_class)
    subject.send(:include, described_class)
  end

  context "(derived model instance)" do
    before { prepare_owners_table }
    let(:model) { subject.send(:include, described_class) }

    describe ".create" do
      it "can create instances" do
        stuff = Stuff.create
        model.create(owner_id: stuff.id, owner_type: stuff.class.name, score: 1, trigram: "abc", fuzzy_field: :name)
      end
    end

    describe ".matches_for" do
      before do
        @paris = Stuff.create(name: "Paris")
        %w(**p *pa par ari ris).each do |trigram|
          model.create(owner_id: @paris.id, owner_type: @paris.class.name, score: 1, fuzzy_field: :name, trigram: trigram)
        end
      end

      it "finds matches" do
        expect(model.matches_for("Paris").map(&:owner_id)).to eq [@paris.id]
      end

      it "finds close matches" do
        expect(model.matches_for("Piriss").map(&:owner_id)).to eq [@paris.id]
      end

      it "does not confuse fields" do
        expect(model.for_field(:name).matches_for("Paris").map(&:owner_id)).to eq [@paris.id]
        expect(model.for_field(:data).matches_for("Paris").map(&:owner_id)).to be_empty
      end

      it "does not confuse owner types" do
        expect(model.for_owner_type(Stuff.name).matches_for("Paris").map(&:owner_id)).to eq [@paris.id]
        expect(model.for_owner_type(Object.name).matches_for("Paris").map(&:owner_id)).to be_empty
      end

      context "(with more than one entry)" do
        before do
          @palma = Stuff.create(name: "Palma")
          %w(**p *pa pal alm lma).each do |trigram|
            model.create(owner_id: @palma.id, owner_type: @palma.class.name, score: 1, fuzzy_field: :name, trigram: trigram)
          end
        end

        it "returns ordered results" do
          expect(model.matches_for("Palmyre").map(&:owner_id)).to eq [@palma.id, @paris.id]
        end
      end
    end
  end
end
