class GeolocationService::Services::ImportBulkDataService
Constants
- Contract
- DEFAULT_CONTRACTS
- Structs
Public Instance Methods
call()
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 18 def call start_time = Time.zone.now load_existing_records load_new_records CSV.foreach(file_path, headers: :first_row) do |row| ip = build_or_find_ip(row) if ip.nil? @invalid_records += 1 next end city = find_record(:city, row['city']&.downcase) if city.nil? country = find_or_build_country(row) city = build_city(row, country) end build_location(row, ip, city) end bulk_save(@new_records[:ip].values, GeolocationService::Structs::IpStruct) bulk_save(@new_records[:country].values, GeolocationService::Structs::CountryStruct) bulk_save(@new_records[:city].values, GeolocationService::Structs::CityStruct) bulk_save(@new_records[:location], GeolocationService::Structs::LocationStruct) GeolocationService::ImportResult.new( imported_records: { ip: @new_records[:ip].values.size, city: @new_records[:city].values.size, country: @new_records[:country].values.size, location: @new_records[:location].size }, invalid_records: @invalid_records, time_consumed: (Time.zone.now - start_time) ) end
Private Instance Methods
build_city(row, country)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 74 def build_city(row, country) return if row['city'].blank? if validate(:city, name: row['city'], country_id: country&.id).success? new_city = Structs::CityStruct.new(@city_count, row['city'], country&.id) @new_records[:city][row['city'].downcase] = new_city @city_count += 1 return new_city end nil end
build_location(row, ip, city)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 103 def build_location(row, ip, city) if validate(:location, latitude: row['latitude']&.to_d, longitude: row['longitude']&.to_d, ip_id: ip&.id, city_id: city&.id).success? @new_records[:location] << Structs::LocationStruct.new(ip.id, row['latitude']&.to_d, row['longitude']&.to_d, city&.id) end end
build_or_find_ip(row)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 58 def build_or_find_ip(row) return if row['ip_address'].blank? existing_ip = find_record(:ip, row['ip_address']) return existing_ip if existing_ip.present? if validate(:ip, address: row['ip_address'], mystery_value: row['mystery_value']).success? new_ip = Structs::IpStruct.new(@ip_count, row['ip_address'], row['mystery_value']) @new_records[:ip][row['ip_address']] = new_ip @ip_count += 1 return new_ip end nil end
bulk_save(all_records, struct, chunk: 1000)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 137 def bulk_save(all_records, struct, chunk: 1000) all_records.each_slice(chunk) do |records| ActiveRecord::Base.connection.execute(struct.insert_sql(records)) end end
find_or_build_country(row)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 87 def find_or_build_country(row) return if row['country_code'].blank? existing_country = find_record(:country, row['country_code']) return existing_country if existing_country.present? if validate(:country, name: row['country'], code: row['country_code']).success? new_country = Structs::CountryStruct.new(@country_count, row['country_code'], row['country']) @new_records[:country][row['country_code']] = new_country @country_count += 1 return new_country end nil end
find_record(type, key)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 127 def find_record(type, key) return if key.nil? @existing_records[type][key] || @new_records[type][key] end
load_existing_records()
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 111 def load_existing_records @existing_records = { ip: Hash[Ip.all.collect { |ip| [ip.address, ip] }], city: Hash[City.all.collect { |city| [city.name.downcase, city] }], country: Hash[Country.all.collect { |country| [country.code.downcase, country] }] } end
load_new_records()
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 119 def load_new_records @ip_count = Ip.count == 0 ? 0 : Ip.last.id + 1 @city_count = City.count == 0 ? 0 : City.last.id + 1 @country_count = Country.count == 0 ? 0 : Country.last.id + 1 @invalid_records = 0 @new_records = {ip: {}, location: [], city: {}, country: {}} end
validate(type, **args)
click to toggle source
# File lib/geolocation_service/services/import_bulk_data_service.rb, line 133 def validate(type, **args) contracts[type].call(args) end