Add api address external data fetch
This commit is contained in:
parent
7eee14feef
commit
228a83f8a5
8 changed files with 392 additions and 127 deletions
46
app/lib/api_address/address_adapter.rb
Normal file
46
app/lib/api_address/address_adapter.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
require 'json_schemer'
|
||||||
|
|
||||||
|
class APIAddress::AddressAdapter
|
||||||
|
class InvalidSchemaError < ::StandardError
|
||||||
|
def initialize(errors)
|
||||||
|
super(errors.map(&:to_json).join("\n"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(search_term)
|
||||||
|
@search_term = search_term
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_params
|
||||||
|
result = Geocoder.search(@search_term, limit: 1).first
|
||||||
|
if result.present? && result.national_address == @search_term
|
||||||
|
feature = result.data['features'].first
|
||||||
|
if schemer.valid?(feature)
|
||||||
|
{
|
||||||
|
label: result.national_address,
|
||||||
|
type: result.result_type,
|
||||||
|
street_address: result.street_address,
|
||||||
|
street_number: result.street_number,
|
||||||
|
street_name: result.street_name,
|
||||||
|
postal_code: result.postal_code,
|
||||||
|
city_name: result.city_name,
|
||||||
|
city_code: result.city_code,
|
||||||
|
department_name: result.department_name,
|
||||||
|
department_code: result.department_code,
|
||||||
|
region_name: result.region_name,
|
||||||
|
region_code: result.region_code,
|
||||||
|
geometry: result.geometry
|
||||||
|
}
|
||||||
|
else
|
||||||
|
errors = schemer.validate(feature).to_a
|
||||||
|
raise InvalidSchemaError.new(errors)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def schemer
|
||||||
|
@schemer ||= JSONSchemer.schema(Rails.root.join('app/schemas/adresse-ban.json'))
|
||||||
|
end
|
||||||
|
end
|
39
app/schemas/adresse-ban.json
Normal file
39
app/schemas/adresse-ban.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://demarches-simplifiees.fr/adresse-ban.schema.json",
|
||||||
|
"title": "Adresse BAN",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"properties": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"label": { "type": "string" },
|
||||||
|
"housenumber": { "type": "string" },
|
||||||
|
"name": { "type": "string" },
|
||||||
|
"postcode": { "type": "string" },
|
||||||
|
"citycode": { "type": "string" },
|
||||||
|
"city": { "type": "string" },
|
||||||
|
"district": { "type": "string" },
|
||||||
|
"context": { "type": "string" },
|
||||||
|
"type": {
|
||||||
|
"enum": ["housenumber", "street", "locality", "municipality"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["label", "type", "name", "postcode", "citycode", "city"]
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "Point"
|
||||||
|
},
|
||||||
|
"coordinates": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["properties"]
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
Geocoder.configure(lookup: :ban_data_gouv_fr)
|
Geocoder.configure(lookup: :ban_data_gouv_fr, use_https: true)
|
||||||
|
|
131
spec/fixtures/files/api_address/address.json
vendored
Normal file
131
spec/fixtures/files/api_address/address.json
vendored
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"version": "draft",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
2.347,
|
||||||
|
48.859
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris",
|
||||||
|
"score": 0.9704590909090908,
|
||||||
|
"id": "75056",
|
||||||
|
"type": "municipality",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "75001",
|
||||||
|
"citycode": "75056",
|
||||||
|
"x": 652089.7,
|
||||||
|
"y": 6862305.26,
|
||||||
|
"population": 2190327,
|
||||||
|
"city": "Paris",
|
||||||
|
"context": "75, Paris, Île-de-France",
|
||||||
|
"importance": 0.67505
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
2.551187,
|
||||||
|
48.357318
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris Foret 77760 Achères-la-Forêt",
|
||||||
|
"score": 0.8608,
|
||||||
|
"id": "77001_b064",
|
||||||
|
"name": "Paris Foret",
|
||||||
|
"postcode": "77760",
|
||||||
|
"citycode": "77001",
|
||||||
|
"x": 666753.6,
|
||||||
|
"y": 6806428.85,
|
||||||
|
"city": "Achères-la-Forêt",
|
||||||
|
"context": "77, Seine-et-Marne, Île-de-France",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.4688
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
6.069561,
|
||||||
|
43.415211
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris 83170 Brignoles",
|
||||||
|
"score": 0.8607481818181817,
|
||||||
|
"id": "83023_05n1tm",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "83170",
|
||||||
|
"citycode": "83023",
|
||||||
|
"x": 948661.53,
|
||||||
|
"y": 6262177.77,
|
||||||
|
"city": "Brignoles",
|
||||||
|
"context": "83, Var, Provence-Alpes-Côte d'Azur",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.46823
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-0.418837,
|
||||||
|
44.758777
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris 33880 Saint-Caprais-de-Bordeaux",
|
||||||
|
"score": 0.8593318181818181,
|
||||||
|
"id": "33381_sy62ut",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "33880",
|
||||||
|
"citycode": "33381",
|
||||||
|
"x": 429522.28,
|
||||||
|
"y": 6412482.95,
|
||||||
|
"city": "Saint-Caprais-de-Bordeaux",
|
||||||
|
"context": "33, Gironde, Nouvelle-Aquitaine",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.45265
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
0.156876,
|
||||||
|
47.33671
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris Buton 37140 Bourgueil",
|
||||||
|
"score": 0.8570918181818181,
|
||||||
|
"id": "37031_b165",
|
||||||
|
"name": "Paris Buton",
|
||||||
|
"postcode": "37140",
|
||||||
|
"citycode": "37031",
|
||||||
|
"x": 485353.99,
|
||||||
|
"y": 6696795.92,
|
||||||
|
"city": "Bourgueil",
|
||||||
|
"context": "37, Indre-et-Loire, Centre-Val de Loire",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.42801
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attribution": "BAN",
|
||||||
|
"licence": "ETALAB-2.0",
|
||||||
|
"query": "Paris",
|
||||||
|
"limit": 5
|
||||||
|
}
|
130
spec/fixtures/files/api_address/address_invalid.json
vendored
Normal file
130
spec/fixtures/files/api_address/address_invalid.json
vendored
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"version": "draft",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
2.347,
|
||||||
|
48.859
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris",
|
||||||
|
"score": 0.9704590909090908,
|
||||||
|
"id": "75056",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "75001",
|
||||||
|
"citycode": "75056",
|
||||||
|
"x": 652089.7,
|
||||||
|
"y": 6862305.26,
|
||||||
|
"population": 2190327,
|
||||||
|
"city": "Paris",
|
||||||
|
"context": "75, Paris, Île-de-France",
|
||||||
|
"importance": 0.67505
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
2.551187,
|
||||||
|
48.357318
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris Foret 77760 Achères-la-Forêt",
|
||||||
|
"score": 0.8608,
|
||||||
|
"id": "77001_b064",
|
||||||
|
"name": "Paris Foret",
|
||||||
|
"postcode": "77760",
|
||||||
|
"citycode": "77001",
|
||||||
|
"x": 666753.6,
|
||||||
|
"y": 6806428.85,
|
||||||
|
"city": "Achères-la-Forêt",
|
||||||
|
"context": "77, Seine-et-Marne, Île-de-France",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.4688
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
6.069561,
|
||||||
|
43.415211
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris 83170 Brignoles",
|
||||||
|
"score": 0.8607481818181817,
|
||||||
|
"id": "83023_05n1tm",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "83170",
|
||||||
|
"citycode": "83023",
|
||||||
|
"x": 948661.53,
|
||||||
|
"y": 6262177.77,
|
||||||
|
"city": "Brignoles",
|
||||||
|
"context": "83, Var, Provence-Alpes-Côte d'Azur",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.46823
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-0.418837,
|
||||||
|
44.758777
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris 33880 Saint-Caprais-de-Bordeaux",
|
||||||
|
"score": 0.8593318181818181,
|
||||||
|
"id": "33381_sy62ut",
|
||||||
|
"name": "Paris",
|
||||||
|
"postcode": "33880",
|
||||||
|
"citycode": "33381",
|
||||||
|
"x": 429522.28,
|
||||||
|
"y": 6412482.95,
|
||||||
|
"city": "Saint-Caprais-de-Bordeaux",
|
||||||
|
"context": "33, Gironde, Nouvelle-Aquitaine",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.45265
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
0.156876,
|
||||||
|
47.33671
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"label": "Paris Buton 37140 Bourgueil",
|
||||||
|
"score": 0.8570918181818181,
|
||||||
|
"id": "37031_b165",
|
||||||
|
"name": "Paris Buton",
|
||||||
|
"postcode": "37140",
|
||||||
|
"citycode": "37031",
|
||||||
|
"x": 485353.99,
|
||||||
|
"y": 6696795.92,
|
||||||
|
"city": "Bourgueil",
|
||||||
|
"context": "37, Indre-et-Loire, Centre-Val de Loire",
|
||||||
|
"type": "street",
|
||||||
|
"importance": 0.42801
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attribution": "BAN",
|
||||||
|
"licence": "ETALAB-2.0",
|
||||||
|
"query": "Paris",
|
||||||
|
"limit": 5
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"limit": 5,
|
|
||||||
"attribution": "BAN",
|
|
||||||
"version": "draft",
|
|
||||||
"licence": "ODbL 1.0",
|
|
||||||
"query": "Paris",
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": []
|
|
||||||
}
|
|
117
spec/fixtures/files/api_adresse/search_results.json
vendored
117
spec/fixtures/files/api_adresse/search_results.json
vendored
|
@ -1,117 +0,0 @@
|
||||||
{
|
|
||||||
"limit": 5,
|
|
||||||
"attribution": "BAN",
|
|
||||||
"version": "draft",
|
|
||||||
"licence": "ODbL 1.0",
|
|
||||||
"query": "Paris",
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"geometry": {
|
|
||||||
"type": "Point",
|
|
||||||
"coordinates": [
|
|
||||||
2.3469,
|
|
||||||
48.8589
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"adm_weight": "6",
|
|
||||||
"citycode": "75056",
|
|
||||||
"name": "Paris",
|
|
||||||
"city": "Paris",
|
|
||||||
"postcode": "75000",
|
|
||||||
"context": "75, \u00cele-de-France",
|
|
||||||
"score": 1.0,
|
|
||||||
"label": "Paris",
|
|
||||||
"id": "75056",
|
|
||||||
"type": "city",
|
|
||||||
"population": "2244"
|
|
||||||
},
|
|
||||||
"type": "Feature"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geometry": {
|
|
||||||
"type": "Point",
|
|
||||||
"coordinates": [
|
|
||||||
4.366801,
|
|
||||||
44.425528
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"citycode": "07330",
|
|
||||||
"postcode": "07150",
|
|
||||||
"name": "Paris",
|
|
||||||
"id": "07330_B095_bd3524",
|
|
||||||
"context": "07, Ard\u00e8che, Rh\u00f4ne-Alpes",
|
|
||||||
"score": 0.8291454545454544,
|
|
||||||
"label": "Paris 07150 Vallon-Pont-d'Arc",
|
|
||||||
"city": "Vallon-Pont-d'Arc",
|
|
||||||
"type": "locality"
|
|
||||||
},
|
|
||||||
"type": "Feature"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geometry": {
|
|
||||||
"type": "Point",
|
|
||||||
"coordinates": [
|
|
||||||
3.564293,
|
|
||||||
45.766413
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"citycode": "63125",
|
|
||||||
"postcode": "63120",
|
|
||||||
"name": "Paris",
|
|
||||||
"city": "Courpi\u00e8re",
|
|
||||||
"context": "63, Puy-de-D\u00f4me, Auvergne",
|
|
||||||
"score": 0.8255363636363636,
|
|
||||||
"label": "Paris 63120 Courpi\u00e8re",
|
|
||||||
"id": "63125_B221_03549b",
|
|
||||||
"type": "locality"
|
|
||||||
},
|
|
||||||
"type": "Feature"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geometry": {
|
|
||||||
"type": "Point",
|
|
||||||
"coordinates": [
|
|
||||||
1.550208,
|
|
||||||
44.673592
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"citycode": "46138",
|
|
||||||
"postcode": "46240",
|
|
||||||
"name": "PARIS (Vaillac)",
|
|
||||||
"city": "C\u0153ur de Causse",
|
|
||||||
"context": "46, Lot, Midi-Pyr\u00e9n\u00e9es",
|
|
||||||
"score": 0.824090909090909,
|
|
||||||
"label": "PARIS (Vaillac) 46240 C\u0153ur de Causse",
|
|
||||||
"id": "46138_XXXX_6ee4ec",
|
|
||||||
"type": "street"
|
|
||||||
},
|
|
||||||
"type": "Feature"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"geometry": {
|
|
||||||
"type": "Point",
|
|
||||||
"coordinates": [
|
|
||||||
-0.526884,
|
|
||||||
43.762253
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"citycode": "40282",
|
|
||||||
"postcode": "40500",
|
|
||||||
"name": "Paris",
|
|
||||||
"city": "Saint-Sever",
|
|
||||||
"context": "40, Landes, Aquitaine",
|
|
||||||
"score": 0.8236181818181818,
|
|
||||||
"label": "Paris 40500 Saint-Sever",
|
|
||||||
"id": "40282_B237_2364e3",
|
|
||||||
"type": "locality"
|
|
||||||
},
|
|
||||||
"type": "Feature"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
45
spec/lib/api_address/address_adapter_spec.rb
Normal file
45
spec/lib/api_address/address_adapter_spec.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
describe APIAddress::AddressAdapter do
|
||||||
|
let(:search_term) { 'Paris' }
|
||||||
|
let(:adapter) { described_class.new(search_term) }
|
||||||
|
subject { adapter.to_params }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Geocoder.configure(lookup: :ban_data_gouv_fr, use_https: true)
|
||||||
|
stub_request(:get, /https:\/\/api-adresse.data.gouv.fr\/search/)
|
||||||
|
.to_return(body: body, status: status)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Geocoder.configure(lookup: :test)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when responds with valid schema" do
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_address/address.json') }
|
||||||
|
let(:status) { 200 }
|
||||||
|
|
||||||
|
it '#to_params returns a valid' do
|
||||||
|
expect(subject).to be_an_instance_of(Hash)
|
||||||
|
expect(subject[:city_name]).to eq(search_term)
|
||||||
|
expect(subject[:city_code]).to eq('75056')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when responds with an address which is not a direct match to search term" do
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_address/address.json') }
|
||||||
|
let(:status) { 200 }
|
||||||
|
let(:search_term) { 'Lyon' }
|
||||||
|
|
||||||
|
it '#to_params ignores the response' do
|
||||||
|
expect(subject).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when responds with invalid schema" do
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_address/address_invalid.json') }
|
||||||
|
let(:status) { 200 }
|
||||||
|
|
||||||
|
it '#to_params raise exception' do
|
||||||
|
expect { subject }.to raise_exception(APIAddress::AddressAdapter::InvalidSchemaError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue