Merge pull request #2830 from betagouv/carto-lib

Carto lib
This commit is contained in:
gregoirenovel 2018-10-15 21:00:11 +02:00 committed by GitHub
commit 288bcff30b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 153 additions and 232 deletions

View file

@ -2,7 +2,7 @@ class Ban::SearchController < ApplicationController
def get
request = params[:request]
json = Carto::Bano::AddressRetriever.new(request).list.map do |value|
json = ApiAdresse::AddressRetriever.new(request).list.map do |value|
{ label: value }
end.to_json
@ -10,7 +10,7 @@ class Ban::SearchController < ApplicationController
end
def get_address_point
point = Carto::Geocodeur.convert_adresse_to_point(params[:request])
point = ApiAdresse::Geocodeur.convert_adresse_to_point(params[:request])
if point.present?
lon = point.x.to_s

View file

@ -0,0 +1,34 @@
module ApiAdresse
# input : address
# output : Array List label address
class AddressRetriever
def initialize(address)
@address = address
end
def list
@list ||= convert_driver_result_to_full_address
end
private
def driver
@driver ||= ApiAdresse::Driver.new(@address, 5)
end
def convert_driver_result_to_full_address
result = JSON.parse(driver.call)
if result['features'].empty?
Rails.logger.error "unable to find location for address #{@address}"
return []
end
result['features'].map do |feature|
feature['properties']['label']
end
rescue TypeError, JSON::ParserError
[]
end
end
end

View file

@ -0,0 +1,18 @@
module ApiAdresse
# input : string (address)
# output : json
class Driver
def initialize(address, limit = 1)
@address = address
@limit = limit
end
def call
search_url = [API_ADRESSE_URL, "search"].join("/")
RestClient.get(search_url, params: { q: @address, limit: @limit })
rescue RestClient::ServiceUnavailable
nil
end
end
end

View file

@ -1,10 +1,10 @@
module Carto
module ApiAdresse
# this class take a string in input and return a point
class Geocodeur
def self.convert_adresse_to_point(address)
Carto::Bano::PointRetriever.new(address).point
ApiAdresse::PointRetriever.new(address).point
rescue RestClient::Exception, JSON::ParserError => e
Rails.logger.error e.message
Rails.logger.error(e.message)
nil
end
end

View file

@ -0,0 +1,28 @@
module ApiAdresse
# input : address
# output : point RGeo::Cartesian::PointImpl
class PointRetriever
def initialize(address)
@address = address
end
def point
@point ||= convert_driver_result_to_point
end
private
def driver
@driver ||= ApiAdresse::Driver.new(@address)
end
def convert_driver_result_to_point
result = JSON.parse(driver.call)
if result['features'].empty?
Rails.logger.error "unable to find location for address #{@address}"
return nil
end
RGeo::GeoJSON.decode(result['features'][0]['geometry'], json_parser: :json)
end
end
end

View file

@ -1,4 +1,4 @@
class CARTO::SGMAP::API
class ApiCarto::API
def initialize
end

View file

@ -1,10 +1,10 @@
class CARTO::SGMAP::Cadastre::Adapter
class ApiCarto::Cadastre::Adapter
def initialize(coordinates)
@coordinates = GeojsonService.to_json_polygon_for_cadastre(coordinates)
end
def data_source
@data_source ||= JSON.parse(CARTO::SGMAP::API.search_cadastre(@coordinates), symbolize_names: true)
@data_source ||= JSON.parse(ApiCarto::API.search_cadastre(@coordinates), symbolize_names: true)
end
def results

View file

@ -1,10 +1,10 @@
class CARTO::SGMAP::QuartiersPrioritaires::Adapter
class ApiCarto::QuartiersPrioritaires::Adapter
def initialize(coordinates)
@coordinates = GeojsonService.to_json_polygon_for_qp(coordinates)
end
def data_source
@data_source ||= JSON.parse(CARTO::SGMAP::API.search_qp(@coordinates), symbolize_names: true)
@data_source ||= JSON.parse(ApiCarto::API.search_qp(@coordinates), symbolize_names: true)
end
def results

25
app/lib/api_geo/driver.rb Normal file
View file

@ -0,0 +1,25 @@
module ApiGeo
class Driver
def self.regions
url = [API_GEO_URL, "regions"].join("/")
call(url)
end
def self.departements
url = [API_GEO_URL, "departements"].join("/")
call(url)
end
def self.pays
File.open('app/lib/api_geo/pays.json').read
end
private
def self.call(url)
RestClient.get(url, params: { fields: :nom })
rescue RestClient::ServiceUnavailable
nil
end
end
end

View file

@ -1,36 +0,0 @@
module Carto
module Bano
# input : address
# output : Array List label address
class AddressRetriever
def initialize(address)
@address = address
end
def list
@list ||= convert_driver_result_to_full_address
end
private
def driver
@driver ||= Carto::Bano::Driver.new @address, 5
end
def convert_driver_result_to_full_address
result = JSON.parse(driver.call)
if result['features'].empty?
Rails.logger.error "unable to find location for address #{@address}"
return []
end
result['features'].map do |feature|
feature['properties']['label']
end
rescue TypeError, JSON::ParserError
[]
end
end
end
end

View file

@ -1,22 +0,0 @@
module Carto
module Bano
# input : string (address)
# output : json
class Driver
def initialize(address, limit = 1)
@address = address
@limit = limit
end
def call
RestClient.get api_url, params: { q: @address, limit: @limit }
rescue RestClient::ServiceUnavailable
nil
end
def api_url
'http://api-adresse.data.gouv.fr/search'
end
end
end
end

View file

@ -1,30 +0,0 @@
module Carto
module Bano
# input : address
# output : point RGeo::Cartesian::PointImpl
class PointRetriever
def initialize(address)
@address = address
end
def point
@point ||= convert_driver_result_to_point
end
private
def driver
@driver ||= Carto::Bano::Driver.new @address
end
def convert_driver_result_to_point
result = JSON.parse(driver.call)
if result['features'].empty?
Rails.logger.error "unable to find location for address #{@address}"
return nil
end
RGeo::GeoJSON.decode(result['features'][0]['geometry'], json_parser: :json)
end
end
end
end

View file

@ -1,27 +0,0 @@
module Carto
module GeoAPI
class Driver
def self.regions
url = [API_GEO_URL, "regions"].join("/")
call(url)
end
def self.departements
url = [API_GEO_URL, "departements"].join("/")
call(url)
end
def self.pays
File.open('app/lib/carto/geo_api/pays.json').read
end
private
def self.call(api_url)
RestClient.get api_url, params: { fields: :nom }
rescue RestClient::ServiceUnavailable
nil
end
end
end
end

View file

@ -1,5 +1,5 @@
class Champs::DepartementChamp < Champs::TextChamp
def self.departements
JSON.parse(Carto::GeoAPI::Driver.departements).map { |liste| "#{liste['code']} - #{liste['nom']}" }.push('99 - Étranger')
JSON.parse(ApiGeo::Driver.departements).map { |liste| "#{liste['code']} - #{liste['nom']}" }.push('99 - Étranger')
end
end

View file

@ -1,5 +1,5 @@
class Champs::PaysChamp < Champs::TextChamp
def self.pays
JSON.parse(Carto::GeoAPI::Driver.pays).pluck("nom")
JSON.parse(ApiGeo::Driver.pays).pluck("nom")
end
end

View file

@ -1,5 +1,5 @@
class Champs::RegionChamp < Champs::TextChamp
def self.regions
JSON.parse(Carto::GeoAPI::Driver.regions).sort_by { |e| e['nom'] }.pluck("nom")
JSON.parse(ApiGeo::Driver.regions).sort_by { |e| e['nom'] }.pluck("nom")
end
end

View file

@ -243,7 +243,7 @@ class Dossier < ApplicationRecord
def geo_position
if etablissement.present?
point = Carto::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse)
point = ApiAdresse::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse)
end
lon = "2.428462"

View file

@ -25,7 +25,7 @@ class ModuleApiCartoService
def self.generate_qp(coordinates)
coordinates.flat_map do |coordinate|
CARTO::SGMAP::QuartiersPrioritaires::Adapter.new(
ApiCarto::QuartiersPrioritaires::Adapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }
).results
end
@ -33,7 +33,7 @@ class ModuleApiCartoService
def self.generate_cadastre(coordinates)
coordinates.flat_map do |coordinate|
CARTO::SGMAP::Cadastre::Adapter.new(
ApiCarto::Cadastre::Adapter.new(
coordinate.map { |element| [element['lng'], element['lat']] }
).results
end

View file

@ -1,12 +1,13 @@
# API URLs
API_ADRESSE_URL = "https://api-adresse.data.gouv.fr"
API_CARTO_URL = "https://apicarto.sgmap.fr"
API_ENTREPRISE_URL = "https://entreprise.api.gouv.fr/v2"
API_GEO_URL = "https://geo.api.gouv.fr"
HELPSCOUT_API_URL = 'https://api.helpscout.net/v2'
PIPEDRIVE_API_URL = 'https://api.pipedrive.com/v1'
HELPSCOUT_API_URL = "https://api.helpscout.net/v2"
PIPEDRIVE_API_URL = "https://api.pipedrive.com/v1"
# Internal URLs
FOG_BASE_URL = 'https://storage.apientreprise.fr'
FOG_BASE_URL = "https://storage.apientreprise.fr"
# External services URLs
DOC_URL = "https://doc.demarches-simplifiees.fr"

View file

@ -8,14 +8,14 @@ describe Ban::SearchController, type: :controller do
subject
end
context 'when request return result', vcr: { cassette_name: 'bano_search_paris' } do
context 'when request return result', vcr: { cassette_name: 'api_adresse_search_paris_2' } do
let (:request) { 'Paris' }
it { expect(response.status).to eq 200 }
it { expect(response.body).to eq '[{"label":"Paris"},{"label":"Paris 63120 Courpière"},{"label":"PARIS (Vaillac) 46240 Cœur de Causse"},{"label":"Paris 40500 Saint-Sever"},{"label":"Paris Buton 37140 Bourgueil"}]' }
end
context 'when request return nothing', vcr: { cassette_name: 'bano_search_nothing' } do
context 'when request return nothing', vcr: { cassette_name: 'api_adresse_search_nothing_2' } do
let (:request) { 'je recherche pas grand chose' }
it { expect(response.status).to eq 200 }
@ -31,13 +31,13 @@ describe Ban::SearchController, type: :controller do
subject
end
context 'when request return result', vcr: { cassette_name: 'ban_search_paris' } do
context 'when request return result', vcr: { cassette_name: 'api_adresse_search_paris' } do
let(:request) { 'Paris' }
it { expect(response.body).to eq ({ lon: '2.3469', lat: '48.8589', zoom: '14', dossier_id: dossier_id }).to_json }
end
context 'when request return nothing', vcr: { cassette_name: 'ban_search_nothing' } do
context 'when request return nothing', vcr: { cassette_name: 'api_adresse_search_nothing' } do
let(:request) { 'je recherche pas grand chose' }
it { expect(response.body).to eq ({ lon: nil, lat: nil, zoom: '14', dossier_id: dossier_id }).to_json }

View file

@ -113,7 +113,7 @@ shared_examples 'carte_controller_spec' do
let(:module_api_carto) { create(:module_api_carto, :with_quartiers_prioritaires) }
before do
allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter)
allow_any_instance_of(ApiCarto::QuartiersPrioritaires::Adapter)
.to receive(:results)
.and_return([{ :code => "QPCODE1234", :nom => "QP de test", :commune => "Paris", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } }])
@ -160,7 +160,7 @@ shared_examples 'carte_controller_spec' do
let(:module_api_carto) { create(:module_api_carto, :with_cadastre) }
before do
allow_any_instance_of(CARTO::SGMAP::Cadastre::Adapter)
allow_any_instance_of(ApiCarto::Cadastre::Adapter)
.to receive(:results)
.and_return([{ :surface_intersection => "0.0006", :surface_parcelle => 11252.692583090324, :numero => "0013", :feuille => 1, :section => "CD", :code_dep => "30", :nom_com => "Le Grau-du-Roi", :code_com => "133", :code_arr => "000", :geometry => { :type => "MultiPolygon", :coordinates => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]] } }])
@ -215,7 +215,7 @@ shared_examples 'carte_controller_spec' do
render_views
before do
allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter)
allow_any_instance_of(ApiCarto::QuartiersPrioritaires::Adapter)
.to receive(:results)
.and_return([{ :code => "QPCODE1234", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } }])

View file

@ -61,7 +61,7 @@ feature 'As a User I wanna create a dossier' do
end
end
scenario 'Identification through siret', vcr: { cassette_name: 'search_ban_paris' }, js: true do
scenario 'Identification through siret', vcr: { cassette_name: 'api_adresse_search_paris_3' }, js: true do
login_as user, scope: :user
visit commencer_path(procedure_path: procedure_with_siret.path)
expect(page).to have_current_path(users_dossier_path(procedure_with_siret.dossiers.last.id.to_s))

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=1&q=50%20av%20des%20champs%20elysees
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=50%20av%20des%20champs%20elysees
body:
encoding: US-ASCII
string: ''

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=1&q=je%20recherche%20pas%20grand%20chose
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=je%20recherche%20pas%20grand%20chose
body:
encoding: US-ASCII
string: ''

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=5&q=je%20recherche%20pas%20grand%20chose
uri: https://api-adresse.data.gouv.fr/search?limit=5&q=je%20recherche%20pas%20grand%20chose
body:
encoding: US-ASCII
string: ''

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=1&q=Paris
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=Paris
body:
encoding: US-ASCII
string: ''

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=5&q=Paris
uri: https://api-adresse.data.gouv.fr/search?limit=5&q=Paris
body:
encoding: US-ASCII
string: ''

View file

@ -2,7 +2,7 @@
http_interactions:
- request:
method: get
uri: http://api-adresse.data.gouv.fr/search?limit=1&q=50%20AV%20DES%20CHAMPS%20ELYSEES%20complement_adresse%2075008%20PARIS%208
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=50%20AV%20DES%20CHAMPS%20ELYSEES%20complement_adresse%2075008%20PARIS%208
body:
encoding: US-ASCII
string: ''

View file

@ -1,70 +0,0 @@
---
http_interactions:
- request:
method: get
uri: https://geo.api.gouv.fr/departements?fields=nom
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- "*/*; q=0.5, application/xml"
Accept-Encoding:
- gzip, deflate
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Server:
- nginx
Date:
- Wed, 19 Oct 2016 09:31:34 GMT
Content-Type:
- application/json; charset=utf-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
Vary:
- Accept-Encoding
- Accept-Encoding
X-Powered-By:
- Express
Access-Control-Allow-Origin:
- "*"
Etag:
- W/"cc1-lXUcIlpPmDfvrGONl0WWsQ"
Strict-Transport-Security:
- max-age=15552000
Content-Encoding:
- gzip
body:
encoding: ASCII-8BIT
string: !binary |-
H4sIAAAAAAAAA22Wy27bMBBFfyXwJpsKqF96dOfYrZsibow4MFAUXTARGxOQ
xZYSjbpF/yfZ5w/0YyVlpDq0sxTmajg8vJzh1z+9Um9773oTVfbe9O51Lt3H
237v75suUpUSsQFjRaGkQXAYBH/IKspl9FHYWkZLo3eyvGeqEdStqIomhfsJ
CccnCRfCqFptA1VMlcmbx/sN10nCsCzL4O80CKvm8YE/Z4zaO4T6b4OQQ/ef
YD8guJN7o8G3T4YX2rpqHSgb3WyaZ7LuE+dUFDuRa8Dpk99UlLUoUAHJTTfC
yLJmgUT2Eo5e2CIN2U03POw+uU21Mc3jb65AcC5cSb/Flc275IPJsQGiVgjF
BRTT5tn5KD+/huMGBN0KHMnzidlqish7aqQNliDkmTa5fuAZDAh5pu0dDmBA
xjPTPG9ZOgm/t4YhQvWhSNbRlVYsmXA/qFJVdfMY5CDeuTDAOqQvD5fPCbRz
fQd2SG5zabCrIWnNlfuRzh4S18fmyQhb1MhLXJdF0W5trQqhgtUJ7rLMubEh
ubWxFzosnwQvqxDNkOw+WSNQHqldCbczbHxEbv44/MKh50fE5iWoaURuB+zH
CrJrY9GkLtzFVT8tE5FhKwPgEdFdaUYIzkV89SfnPiK4K/07JDciuYU/s1fY
j8hwIcqg147J0LUTnvqY8A6AjhVEuBB736m7wxsT30JaU2/a+ha6ks5pEBKg
E/K6j8lvoc2d2gi05jEhniYmvc9uUuxogDHpfXadBBWR2bViQTGJXQfAYgJb
inaYujEgFEwbE9nS7r1mFnaimNyWe9M8lc2Tn7X/vcd8rwzl7p9uRzE5Ium1
UW7SiIIXKybUC7ePmw2fGzGpel8cx8n1eEbGJHsw1UqEYzQh4UPwFVsnhL0S
3lzdbhNSXomdVgwGLbF97JxISHXpXjAgnpDkSvpLdzqHEyI8iLzzwwuWEOSX
nSxcLi5EjjNpf0Wr1sGUkOZKbznQUmK8dSt3eFKy86FXe09KiGuBaZeS4FrY
+yK4synprWWZO/ticfJbO/exZ6TkdrDHiYTU1rp6IJCUzL6EMzQlrFtp3LvU
N+uzXJ5dyOK7NmjOGeG9r6owU3bcGdur3h5zt88s8GDrk5Vr0XU0k+55AF0I
s/CpjoySBUCFk5yHTSkj07kVuSy0/cFiguvi0tfujRJMsSy4M3O7F8FmkmAW
irOb5smWiq/kLAnauNjrmi/YzF+Jb/8A5ygzwMEMAAA=
http_version:
recorded_at: Wed, 19 Oct 2016 09:31:33 GMT
recorded_with: VCR 3.0.1

View file

@ -1,6 +1,6 @@
require 'spec_helper'
describe Carto::Bano::AddressRetriever do
describe ApiAdresse::AddressRetriever do
describe '#list' do
let(:request) { 'Paris' }
let(:response) { File.open('spec/support/files/ban_address_search.json') }
@ -9,7 +9,7 @@ describe Carto::Bano::AddressRetriever do
subject { described_class.new(request).list }
before do
stub_request(:get, "http://api-adresse.data.gouv.fr/search?&q=#{request}&limit=5")
stub_request(:get, "https://api-adresse.data.gouv.fr/search?&q=#{request}&limit=5")
.to_return(status: status, body: response, headers: {})
end

View file

@ -1,14 +1,14 @@
require 'spec_helper'
describe Carto::Geocodeur do
describe ApiAdresse::Geocodeur do
let(:address) { '50 av des champs elysees' }
describe '.convert_adresse_to_point', vcr: { cassette_name: 'bano_octo' } do
describe '.convert_adresse_to_point', vcr: { cassette_name: 'api_adresse_octo' } do
it 'return a point' do
expect(described_class.convert_adresse_to_point(address).class).to eq(RGeo::Cartesian::PointImpl)
end
context 'when RestClient::Exception' do
before do
allow_any_instance_of(Carto::Bano::Driver).to receive(:call).and_raise(RestClient::Exception)
allow_any_instance_of(ApiAdresse::Driver).to receive(:call).and_raise(RestClient::Exception)
end
it 'return nil' do
expect(described_class.convert_adresse_to_point(address)).to be_nil
@ -16,7 +16,7 @@ describe Carto::Geocodeur do
end
context 'when JSON::ParserError' do
before do
allow_any_instance_of(Carto::Bano::PointRetriever).to receive(:point).and_raise(JSON::ParserError)
allow_any_instance_of(ApiAdresse::PointRetriever).to receive(:point).and_raise(JSON::ParserError)
end
it 'return nil' do
expect(described_class.convert_adresse_to_point(address)).to be_nil

View file

@ -1,6 +1,6 @@
require 'spec_helper'
describe CARTO::SGMAP::API do
describe ApiCarto::API do
describe '.search_qp' do
subject { described_class.search_qp(geojson) }

View file

@ -1,6 +1,6 @@
require 'spec_helper'
describe CARTO::SGMAP::Cadastre::Adapter do
describe ApiCarto::Cadastre::Adapter do
subject { described_class.new(coordinates).results }
before do

View file

@ -1,6 +1,6 @@
require 'spec_helper'
describe CARTO::SGMAP::QuartiersPrioritaires::Adapter do
describe ApiCarto::QuartiersPrioritaires::Adapter do
subject { described_class.new(coordinates).results }
before do

View file

@ -1,13 +1,13 @@
require 'spec_helper'
describe Carto::GeoAPI::Driver do
describe '.regions', vcr: { cassette_name: 'geoapi_regions' } do
describe ApiGeo::Driver do
describe '.regions', vcr: { cassette_name: 'api_geo_regions' } do
subject { described_class.regions }
it { expect(subject.code).to eq 200 }
end
describe '.departements', vcr: { cassette_name: 'geoapi_departements' } do
describe '.departements', vcr: { cassette_name: 'api_geo_departements' } do
subject { described_class.departements }
it { expect(subject.code).to eq 200 }
@ -16,6 +16,6 @@ describe Carto::GeoAPI::Driver do
describe '.pays' do
subject { described_class.pays }
it { is_expected.to eq File.open('app/lib/carto/geo_api/pays.json').read }
it { is_expected.to eq File.open('app/lib/api_geo/pays.json').read }
end
end

View file

@ -26,7 +26,7 @@ shared_examples 'champ_spec' do
end
end
describe '.departement', vcr: { cassette_name: 'call_geo_api_departements' } do
describe '.departement', vcr: { cassette_name: 'api_geo_departements' } do
subject { Champs::DepartementChamp.departements }
it { expect(subject).to include '99 - Étranger' }