# frozen_string_literal: true FactoryBot.define do factory :point do battery_status { 1 } ping { 'MyString' } battery { 1 } topic { 'MyString' } altitude { 1 } longitude { FFaker::Geolocation.lng } velocity { 0 } trigger { 1 } bssid { 'MyString' } ssid { 'MyString' } connection { 1 } vertical_accuracy { 1 } accuracy { 1 } timestamp { DateTime.new(2024, 5, 1).to_i + rand(1_000).minutes } latitude { FFaker::Geolocation.lat } mode { 1 } inrids { 'MyString' } in_regions { 'MyString' } raw_data { '' } tracker_id { 'MyString' } import_id { '' } city { nil } reverse_geocoded_at { nil } course { nil } course_accuracy { nil } external_track_id { nil } lonlat { "POINT(#{FFaker::Geolocation.lng} #{FFaker::Geolocation.lat})" } user country_id { nil } # Add transient attribute to handle country strings transient do country { nil } # Allow country to be passed as string end # Handle country string assignment by creating Country objects after(:create) do |point, evaluator| if evaluator.country.is_a?(String) # Set both the country string attribute and the Country association country_obj = Country.find_or_create_by(name: evaluator.country) do |country| iso_a2, iso_a3 = Countries::IsoCodeMapper.fallback_codes_from_country_name(evaluator.country) country.iso_a2 = iso_a2 country.iso_a3 = iso_a3 country.geom = "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)))" end point.update_columns( country: evaluator.country, country_name: evaluator.country, country_id: country_obj.id ) elsif evaluator.country point.update_columns( country: evaluator.country.name, country_name: evaluator.country.name, country_id: evaluator.country.id ) end end trait :with_known_location do lonlat { 'POINT(37.6173 55.755826)' } end trait :with_geodata do geodata do { 'type' => 'Feature', 'geometry' => { 'type' => 'Point', 'coordinates' => [37.6177036, 55.755847] }, 'properties' => { 'city' => 'Moscow', 'name' => 'Kilometre zero', 'type' => 'house', 'state' => 'Moscow', 'osm_id' => 583_204_619, 'street' => 'Манежная площадь', 'country' => 'Russia', 'osm_key' => 'tourism', 'district' => 'Tverskoy', 'osm_type' => 'N', 'postcode' => '103265', 'osm_value' => 'attraction', 'countrycode' => 'RU' } } end end trait :reverse_geocoded do city { FFaker::Address.city } reverse_geocoded_at { Time.current } after(:build) do |point, evaluator| # Only set country if not already set by transient attribute unless point.read_attribute(:country) country_name = FFaker::Address.country country_obj = Country.find_or_create_by(name: country_name) do |country| iso_a2, iso_a3 = Countries::IsoCodeMapper.fallback_codes_from_country_name(country_name) country.iso_a2 = iso_a2 country.iso_a3 = iso_a3 country.geom = "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)))" end point.write_attribute(:country, country_name) # Set the legacy string attribute point.write_attribute(:country_name, country_name) # Set the new string attribute point.country_id = country_obj.id # Set the association end end end end end