decoupage_administratif 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +55 -0
- data/CHANGELOG.md +35 -0
- data/LICENSE.txt +21 -0
- data/README.md +320 -0
- data/Rakefile +14 -0
- data/data/communes.json +37640 -0
- data/data/departements.json +111 -0
- data/data/epci.json +1257 -0
- data/data/regions.json +28 -0
- data/lib/decoupage_administratif/base_model.rb +60 -0
- data/lib/decoupage_administratif/commune.rb +82 -0
- data/lib/decoupage_administratif/config.rb +47 -0
- data/lib/decoupage_administratif/departement.rb +51 -0
- data/lib/decoupage_administratif/epci.rb +61 -0
- data/lib/decoupage_administratif/parser.rb +41 -0
- data/lib/decoupage_administratif/railtie.rb +11 -0
- data/lib/decoupage_administratif/region.rb +50 -0
- data/lib/decoupage_administratif/search.rb +181 -0
- data/lib/decoupage_administratif/territory_extensions.rb +35 -0
- data/lib/decoupage_administratif/territory_strategies.rb +87 -0
- data/lib/decoupage_administratif/version.rb +7 -0
- data/lib/decoupage_administratif.rb +26 -0
- data/lib/tasks/install.rake +59 -0
- data/sig/decoupage_administratif/base_model.rbs +7 -0
- data/sig/decoupage_administratif/commune.rbs +32 -0
- data/sig/decoupage_administratif/departement.rbs +24 -0
- data/sig/decoupage_administratif/epci.rbs +23 -0
- data/sig/decoupage_administratif/parser.rbs +11 -0
- data/sig/decoupage_administratif/region.rbs +21 -0
- data/sig/decoupage_administratif/search.rbs +20 -0
- data/sig/decoupage_administratif/territory_extensions.rbs +11 -0
- data/sig/decoupage_administratif/territory_strategies.rbs +51 -0
- data/sig/decoupage_administratif.rbs +4 -0
- metadata +96 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DecoupageAdministratif
|
4
|
+
module TerritoryStrategies
|
5
|
+
class Base
|
6
|
+
def initialize(territory)
|
7
|
+
@territory = territory
|
8
|
+
end
|
9
|
+
|
10
|
+
def intersects_with_insee_codes?(commune_insee_codes)
|
11
|
+
return false if commune_insee_codes.empty?
|
12
|
+
|
13
|
+
perform_intersection(commune_insee_codes)
|
14
|
+
end
|
15
|
+
|
16
|
+
def insee_codes
|
17
|
+
@insee_codes ||= calculate_insee_codes
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :territory
|
23
|
+
|
24
|
+
def perform_intersection(commune_insee_codes)
|
25
|
+
raise NotImplementedError, "Must be implemented by subclass"
|
26
|
+
end
|
27
|
+
|
28
|
+
def calculate_insee_codes
|
29
|
+
raise NotImplementedError, "Must be implemented by subclass"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class CommuneStrategy < Base
|
34
|
+
private
|
35
|
+
|
36
|
+
def perform_intersection(commune_insee_codes)
|
37
|
+
commune_insee_codes.include?(territory.code)
|
38
|
+
end
|
39
|
+
|
40
|
+
def calculate_insee_codes
|
41
|
+
[territory.code]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class DepartementStrategy < Base
|
46
|
+
private
|
47
|
+
|
48
|
+
def perform_intersection(commune_insee_codes)
|
49
|
+
departement_prefix = territory.code.length == 2 ? territory.code : territory.code[0..1]
|
50
|
+
commune_insee_codes.any? { |commune_code| commune_code.start_with?(departement_prefix) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def calculate_insee_codes
|
54
|
+
territory.communes.map(&:code)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class RegionStrategy < Base
|
59
|
+
private
|
60
|
+
|
61
|
+
def perform_intersection(commune_insee_codes)
|
62
|
+
departement_codes = territory.departements.map(&:code)
|
63
|
+
commune_insee_codes.any? do |commune_code|
|
64
|
+
dept_code = commune_code.length >= 3 && commune_code[0..1].to_i >= 96 ? commune_code[0..2] : commune_code[0..1]
|
65
|
+
departement_codes.include?(dept_code)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def calculate_insee_codes
|
70
|
+
territory.communes.map(&:code)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class EpciStrategy < Base
|
75
|
+
private
|
76
|
+
|
77
|
+
def perform_intersection(commune_insee_codes)
|
78
|
+
epci_commune_codes = territory.membres.map { |membre| membre[:code] || membre["code"] }
|
79
|
+
(epci_commune_codes & commune_insee_codes).any?
|
80
|
+
end
|
81
|
+
|
82
|
+
def calculate_insee_codes
|
83
|
+
territory.membres.map { |membre| membre[:code] || membre["code"] }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "decoupage_administratif/version"
|
4
|
+
require_relative "decoupage_administratif/config"
|
5
|
+
require_relative "decoupage_administratif/base_model"
|
6
|
+
require_relative "decoupage_administratif/territory_strategies"
|
7
|
+
require_relative "decoupage_administratif/territory_extensions"
|
8
|
+
require_relative "decoupage_administratif/parser"
|
9
|
+
require_relative "decoupage_administratif/commune"
|
10
|
+
require_relative "decoupage_administratif/departement"
|
11
|
+
require_relative "decoupage_administratif/region"
|
12
|
+
require_relative "decoupage_administratif/epci"
|
13
|
+
require_relative "decoupage_administratif/search"
|
14
|
+
|
15
|
+
require 'decoupage_administratif/railtie' if defined?(Rails)
|
16
|
+
|
17
|
+
module DecoupageAdministratif
|
18
|
+
class Error < StandardError; end
|
19
|
+
class NotFoundError < Error; end
|
20
|
+
|
21
|
+
# Returns information about the embedded data version
|
22
|
+
# @return [String] formatted string with data version information
|
23
|
+
def self.data_info
|
24
|
+
"Data version: #{DATA_VERSION} (from #{DATA_SOURCE})"
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'json'
|
6
|
+
require_relative '../decoupage_administratif/config'
|
7
|
+
|
8
|
+
def download_file(url, destination)
|
9
|
+
puts "Downloading from #{url}..."
|
10
|
+
|
11
|
+
uri = URI(url)
|
12
|
+
response = Net::HTTP.get_response(uri)
|
13
|
+
|
14
|
+
raise "Download failed with status: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
|
15
|
+
|
16
|
+
File.binwrite(destination, response.body)
|
17
|
+
puts "Successfully downloaded"
|
18
|
+
|
19
|
+
# Validate JSON
|
20
|
+
begin
|
21
|
+
JSON.parse(File.read(destination))
|
22
|
+
puts "JSON validation successful"
|
23
|
+
rescue JSON::ParserError => e
|
24
|
+
puts "Error: Invalid JSON file downloaded"
|
25
|
+
puts e.message
|
26
|
+
FileUtils.rm(destination)
|
27
|
+
raise "Download failed: Invalid JSON"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
namespace :decoupage_administratif do
|
32
|
+
desc 'Update files'
|
33
|
+
task :update do
|
34
|
+
collection = %w[communes departements regions epci]
|
35
|
+
data_dir = DecoupageAdministratif::Config.data_directory
|
36
|
+
FileUtils.mkdir_p(data_dir)
|
37
|
+
|
38
|
+
collection.each do |item|
|
39
|
+
file = File.join(data_dir, "#{item}.json")
|
40
|
+
url = "https://unpkg.com/@etalab/decoupage-administratif@4.0.0/data/#{item}.json"
|
41
|
+
|
42
|
+
download_file(url, file)
|
43
|
+
|
44
|
+
puts "Update completed successfully!"
|
45
|
+
rescue StandardError => e
|
46
|
+
puts "Error during update:"
|
47
|
+
puts e.message
|
48
|
+
puts e.backtrace
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Download files'
|
54
|
+
task :install do
|
55
|
+
data_dir = DecoupageAdministratif::Config.data_directory
|
56
|
+
FileUtils.rm_rf(data_dir) if File.directory?(data_dir)
|
57
|
+
Rake::Task['decoupage_administratif:update'].invoke
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
extend BaseModel
|
3
|
+
class Commune
|
4
|
+
extend BaseModel
|
5
|
+
include TerritoryExtensions
|
6
|
+
attr_reader code: String
|
7
|
+
attr_reader nom: String
|
8
|
+
attr_reader zone: String
|
9
|
+
attr_reader region_code: String
|
10
|
+
attr_reader departement_code: String
|
11
|
+
attr_reader commune_type: String
|
12
|
+
|
13
|
+
def initialize: (
|
14
|
+
code: String,
|
15
|
+
nom: String,
|
16
|
+
zone: String,
|
17
|
+
region_code: String,
|
18
|
+
departement_code: String,
|
19
|
+
commune_type: Symbol
|
20
|
+
) -> void
|
21
|
+
|
22
|
+
def self.all: () -> Array[Commune]
|
23
|
+
|
24
|
+
def self.communes_actuelles: () -> Array[Commune]
|
25
|
+
|
26
|
+
def region: () -> Region
|
27
|
+
|
28
|
+
def departement: () -> Departement
|
29
|
+
|
30
|
+
def epci: () -> Epci?
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
class Departement
|
3
|
+
extend BaseModel
|
4
|
+
include TerritoryExtensions
|
5
|
+
attr_reader code: String
|
6
|
+
attr_reader nom: String
|
7
|
+
attr_reader zone: String
|
8
|
+
attr_reader code_region: String
|
9
|
+
|
10
|
+
def initialize: (
|
11
|
+
code: String,
|
12
|
+
nom: String,
|
13
|
+
zone: String,
|
14
|
+
code_region: String
|
15
|
+
) -> void
|
16
|
+
|
17
|
+
|
18
|
+
def self.all: () -> Array[Departement]
|
19
|
+
|
20
|
+
def communes: () -> Array[Commune]
|
21
|
+
|
22
|
+
def region: () -> Region
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
class Epci
|
3
|
+
extend BaseModel
|
4
|
+
include TerritoryExtensions
|
5
|
+
attr_reader code: String
|
6
|
+
attr_reader nom: String
|
7
|
+
attr_reader membres: Array[{ code: String, nom: String }]
|
8
|
+
|
9
|
+
def initialize: (
|
10
|
+
code: String,
|
11
|
+
nom: String,
|
12
|
+
membres: Array[{ code: String, nom: String }]
|
13
|
+
) -> void
|
14
|
+
|
15
|
+
def self.all: () -> Array[Epci]
|
16
|
+
|
17
|
+
def self.search_by_communes_codes: (Array[String]) -> Array[Epci]
|
18
|
+
|
19
|
+
def communes: () -> Array[Commune]
|
20
|
+
|
21
|
+
def regions: () -> Array[Region]
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
class Region
|
3
|
+
extend BaseModel
|
4
|
+
include TerritoryExtensions
|
5
|
+
attr_reader code: String
|
6
|
+
attr_reader nom: String
|
7
|
+
attr_reader zone: String
|
8
|
+
|
9
|
+
def initialize: (
|
10
|
+
code: String,
|
11
|
+
nom: String,
|
12
|
+
zone: String,
|
13
|
+
) -> void
|
14
|
+
|
15
|
+
def self.all: () -> Array[Region]
|
16
|
+
|
17
|
+
def communes: () -> Array[Commune]
|
18
|
+
|
19
|
+
def departements: () -> Array[Departement]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
class Search
|
3
|
+
attr_reader codes: Array[String] | nil
|
4
|
+
attr_reader regions: Array[Region] | nil
|
5
|
+
attr_reader departements: Array[Departement] | nil
|
6
|
+
attr_reader epcis: Array[Epci] | nil
|
7
|
+
attr_reader communes: Array[Commune] | nil
|
8
|
+
|
9
|
+
def by_insee_codes: () -> Hash[Symbol, Array[Region] | Array[Departement] | Array[Epci] | Array[Commune]]
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def find_communes_by_codes: () -> Hash[Departement, Array[Commune]]
|
14
|
+
|
15
|
+
def search_for_communes: () -> void
|
16
|
+
def search_for_departements: () -> void
|
17
|
+
def search_for_epcis: () -> void
|
18
|
+
def search_for_region: () -> void
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
module TerritoryExtensions
|
3
|
+
def territory_intersects_with_insee_codes?: (Array[String] commune_insee_codes) -> bool
|
4
|
+
|
5
|
+
def territory_insee_codes: () -> Array[String]
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def territory_strategy: () -> TerritoryStrategies::Base
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module DecoupageAdministratif
|
2
|
+
module TerritoryStrategies
|
3
|
+
class Base
|
4
|
+
def initialize: (untyped territory) -> void
|
5
|
+
|
6
|
+
def intersects_with_insee_codes?: (Array[String] commune_insee_codes) -> bool
|
7
|
+
|
8
|
+
def insee_codes: () -> Array[String]
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
attr_reader territory: untyped
|
13
|
+
|
14
|
+
def perform_intersection: (Array[String] commune_insee_codes) -> bool
|
15
|
+
|
16
|
+
def calculate_insee_codes: () -> Array[String]
|
17
|
+
end
|
18
|
+
|
19
|
+
class CommuneStrategy < Base
|
20
|
+
private
|
21
|
+
|
22
|
+
def perform_intersection: (Array[String] commune_insee_codes) -> bool
|
23
|
+
|
24
|
+
def calculate_insee_codes: () -> Array[String]
|
25
|
+
end
|
26
|
+
|
27
|
+
class DepartementStrategy < Base
|
28
|
+
private
|
29
|
+
|
30
|
+
def perform_intersection: (Array[String] commune_insee_codes) -> bool
|
31
|
+
|
32
|
+
def calculate_insee_codes: () -> Array[String]
|
33
|
+
end
|
34
|
+
|
35
|
+
class RegionStrategy < Base
|
36
|
+
private
|
37
|
+
|
38
|
+
def perform_intersection: (Array[String] commune_insee_codes) -> bool
|
39
|
+
|
40
|
+
def calculate_insee_codes: () -> Array[String]
|
41
|
+
end
|
42
|
+
|
43
|
+
class EpciStrategy < Base
|
44
|
+
private
|
45
|
+
|
46
|
+
def perform_intersection: (Array[String] commune_insee_codes) -> bool
|
47
|
+
|
48
|
+
def calculate_insee_codes: () -> Array[String]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: decoupage_administratif
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lucien Mollard
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-08-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Ruby gem for French administrative divisions (découpage administratif
|
28
|
+
français). Access data about all French communes (municipalities), départements,
|
29
|
+
régions, and EPCIs (intercommunalités). Official data from @etalab/decoupage-administratif.
|
30
|
+
email:
|
31
|
+
- lucien.mollard@beta.gouv.fr
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".rspec"
|
37
|
+
- ".rubocop.yml"
|
38
|
+
- CHANGELOG.md
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- data/communes.json
|
43
|
+
- data/departements.json
|
44
|
+
- data/epci.json
|
45
|
+
- data/regions.json
|
46
|
+
- lib/decoupage_administratif.rb
|
47
|
+
- lib/decoupage_administratif/base_model.rb
|
48
|
+
- lib/decoupage_administratif/commune.rb
|
49
|
+
- lib/decoupage_administratif/config.rb
|
50
|
+
- lib/decoupage_administratif/departement.rb
|
51
|
+
- lib/decoupage_administratif/epci.rb
|
52
|
+
- lib/decoupage_administratif/parser.rb
|
53
|
+
- lib/decoupage_administratif/railtie.rb
|
54
|
+
- lib/decoupage_administratif/region.rb
|
55
|
+
- lib/decoupage_administratif/search.rb
|
56
|
+
- lib/decoupage_administratif/territory_extensions.rb
|
57
|
+
- lib/decoupage_administratif/territory_strategies.rb
|
58
|
+
- lib/decoupage_administratif/version.rb
|
59
|
+
- lib/tasks/install.rake
|
60
|
+
- sig/decoupage_administratif.rbs
|
61
|
+
- sig/decoupage_administratif/base_model.rbs
|
62
|
+
- sig/decoupage_administratif/commune.rbs
|
63
|
+
- sig/decoupage_administratif/departement.rbs
|
64
|
+
- sig/decoupage_administratif/epci.rbs
|
65
|
+
- sig/decoupage_administratif/parser.rbs
|
66
|
+
- sig/decoupage_administratif/region.rbs
|
67
|
+
- sig/decoupage_administratif/search.rbs
|
68
|
+
- sig/decoupage_administratif/territory_extensions.rbs
|
69
|
+
- sig/decoupage_administratif/territory_strategies.rbs
|
70
|
+
homepage: https://github.com/betagouv/decoupage-administratif-gem
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata:
|
74
|
+
homepage_uri: https://github.com/betagouv/decoupage-administratif-gem
|
75
|
+
changelog_uri: https://github.com/betagouv/decoupage-administratif-gem/blob/main/CHANGELOG.md
|
76
|
+
rubygems_mfa_required: 'true'
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 3.0.0
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.5.11
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: French administrative divisions - Découpage administratif français
|
96
|
+
test_files: []
|