From 39be7c17ce987bd68904d55b723c5922af64aa48 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 31 Oct 2023 19:03:16 -0400 Subject: [PATCH] Resolve Homes lose street_number after canonicalization #495 (#497) * Update code to read Pelias data correctly. * Add test for failing case. * Fix matching algorithm. Co-authored-by: Anna Westland-Tegart Co-authored-by: Linden Huhmann Co-authored-by: Thiago Bardini Co-authored-by: Mike Lynch --- backend/app/jobs/canonicalize_address_job.rb | 33 ++++++++++++------- .../jobs/canonicalize_address_job_spec.rb | 7 +++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/backend/app/jobs/canonicalize_address_job.rb b/backend/app/jobs/canonicalize_address_job.rb index 5761f320..269d897b 100644 --- a/backend/app/jobs/canonicalize_address_job.rb +++ b/backend/app/jobs/canonicalize_address_job.rb @@ -28,22 +28,33 @@ def perform(home_id) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metr 'country': 'USA', 'postalcode': home_map[:zip_code] }) - result = JSON.parse(response.body)['features'] + # TODO: handle response failing + results = JSON.parse(response.body)['features'] - exact_match = result.select do |feature| - feature['properties']['housenumber'] == home_map['street_number'] && - feature['properties']['street'] == home_map['street_name'] - end - match_to_use = exact_match.empty? ? result.first : exact_match.first + # rubocop:disable Style/MultilineBlockChain + match_to_use = if (match = results.select { |r| r['properties']['match_type'] == 'exact' }.first) + # Try taking first 'exact' match + match['properties'] + elsif (match = results.select do |r| + r['properties']['match_type'] == 'interpolated' + end.max_by { |r| r['properties']['confidence'].to_f }) + # Then fall back to highest confidence 'interpolated' result + match['properties'] + end + # If couldn't find any match, match_to_use is nil + # rubocop:enable Style/MultilineBlockChain if match_to_use + # If we got some result back from Pelias, figure out what needs changing i.e. build change_map + # Compare match_to_use against home_map change_map = {} - if change_map[:street_number] != match_to_use['housenumber'].to_s + + if home_map[:street_number] != match_to_use['housenumber'].to_s change_map[:street_number] = match_to_use['housenumber'].to_s end - change_map[:city] = match_to_use['locality'] if change_map[:city] != match_to_use['locality'] - change_map[:state] = match_to_use['region'] if change_map[:state] != match_to_use['region'] - change_map[:zip_code] = match_to_use['postalcode'] if change_map[:zip_code] != match_to_use['postalcode'] + change_map[:city] = match_to_use['locality'] if home_map[:city] != match_to_use['locality'] + change_map[:state] = match_to_use['region'] if home_map[:state] != match_to_use['region'] + change_map[:zip_code] = match_to_use['postalcode'] if home_map[:zip_code] != match_to_use['postalcode'] else change_map = nil end @@ -66,7 +77,7 @@ def perform(home_id) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metr change_map[:status] = Home.statuses[:canonicalized] home.update_columns change_map # rubocop:disable Rails/SkipsModelValidations else - # If find match, then move survey visits to existing home and delete + # If find match for existing_home, then move survey visits to existing home and delete ActiveRecord::Base.transaction do home.survey_visits.each do |sv| sv.home = existing_home diff --git a/backend/spec/jobs/canonicalize_address_job_spec.rb b/backend/spec/jobs/canonicalize_address_job_spec.rb index 7d81ac46..5c3f0108 100644 --- a/backend/spec/jobs/canonicalize_address_job_spec.rb +++ b/backend/spec/jobs/canonicalize_address_job_spec.rb @@ -3,5 +3,10 @@ require 'rails_helper' RSpec.describe CanonicalizeAddressJob, type: :job do - pending "add some examples to (or delete) #{__FILE__}" + let(:home) { create(:home) } + it 'canonicalizes an address properly' do + CanonicalizeAddressJob.perform_now(home.id) + home.reload + expect(home.street_number).not_to be_nil + end end