municipitaly2 2.0.3 → 2.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 119733e32f643897b995092012e46df76c7046a8d2da5538f1c498c7b8a9b807
4
- data.tar.gz: 5a5ee1883bcbf6376c351ece7d7c1fb3b628a9da110bd4a77eacd41d6189d440
3
+ metadata.gz: b5f242aa4e86895e37a07b2dd7448cc6a63affa93019ce88653ccdfb720d464b
4
+ data.tar.gz: 1a841723aa37345e8010651fb284818e18baa83b04c599a9f043d97ed647e146
5
5
  SHA512:
6
- metadata.gz: 639974c60b4f5f0f67a571427292cda0af2c77453572bb91ac67ee680d858ad59174a145e791fac6138d66b94af9c768b77a2ab95a139f91814234cea180d5b1
7
- data.tar.gz: 9c9d2151e3c427894d00d0820e40bf5749e0c02b4f5a8b527841b38fc4c1bb206cc7895f67eaf0f109f14f0c20e429ae66a51ff5f8143f01bab2c7b057a0a7b4
6
+ metadata.gz: 973a9d71498055176f540226b3a00ccc70d914ad80965f02348740cb370f02855a0f765657ef9d4f2d75989d10e5eac9a59788a63577a0baa195899037ae5d7c
7
+ data.tar.gz: 4b7a3a72913d9dd9657f06db6966e4d358586b787b0a50a558e3f044f96e9df688362fb85d1b2762f7d3bc1c629e2dfdc0d552c44d7bedb9d5831c482ddff7cf
data/CHANGELOG.md CHANGED
@@ -5,9 +5,23 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.5] - 2026-11-05
9
+
10
+ - Updated database
11
+ - Province changes: Sardinia was reorganized, so Sassari (`090`), Nuoro (`091`), Cagliari (`092`), Oristano (`095`) and Sud Sardegna (`111`) have new istat codes in the range `112`-`119` (e.g. Alghero is now `112001`, it was `090003`)
12
+ - Municipality changes: Castegnero and Nanto merged into Castegnero Nanto, Lirio merged into Montalto Pavese, Murisengo is now Murisengo Monferrato, Vallecrosia is now Vallecrosia al mare, Tripi is now Tripi - Abakainon
13
+ - Updated gems
14
+ - Improved tool/generate.rb (use `-u` to update sources and `-g` to generate data)
15
+
16
+ ## [2.0.4] - 2025-09-09
17
+
18
+ - Updated database
19
+ - Updated gems
20
+ - Improved search municipalities results order
21
+
8
22
  ## [2.0.3] - 2024-12-17
9
23
 
10
- - Search region by its name: `Municipitaly::Search.province_from_name('a province')`
24
+ - Search region by its name: `Municipitaly::Search.region_from_name('a region')`
11
25
  - Fixed and tested specs
12
26
 
13
27
  ## [2.0.2] - 2024-12-13
data/Gemfile CHANGED
@@ -4,3 +4,9 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in fitbark.gemspec
6
6
  gemspec
7
+
8
+ gem 'bundler', '~> 4.0'
9
+ gem 'rake', '~> 13.4'
10
+ gem 'rspec', '~> 3.13'
11
+ gem 'rubocop', '~> 1.92'
12
+ gem 'simplecov', '~> 1.3'
data/Gemfile.lock CHANGED
@@ -1,75 +1,99 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- municipitaly2 (2.0.3)
4
+ municipitaly2 (2.0.5)
5
5
  csv (>= 3.3.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.2)
11
- csv (3.3.1)
12
- diff-lcs (1.5.1)
13
- docile (1.4.0)
14
- json (2.7.2)
15
- language_server-protocol (3.17.0.3)
16
- parallel (1.25.1)
17
- parser (3.3.4.0)
10
+ ast (2.4.3)
11
+ csv (3.3.7)
12
+ diff-lcs (1.6.2)
13
+ json (3.1.0)
14
+ language_server-protocol (3.17.0.6)
15
+ lint_roller (1.1.0)
16
+ parallel (2.3.0)
17
+ parser (3.3.13.0)
18
18
  ast (~> 2.4.1)
19
19
  racc
20
- racc (1.8.0)
20
+ prism (1.9.0)
21
+ racc (1.8.1)
21
22
  rainbow (3.1.1)
22
- rake (13.2.1)
23
- regexp_parser (2.9.2)
24
- rexml (3.3.2)
25
- strscan
26
- rspec (3.13.0)
23
+ rake (13.4.2)
24
+ regexp_parser (2.13.1)
25
+ rspec (3.13.2)
27
26
  rspec-core (~> 3.13.0)
28
27
  rspec-expectations (~> 3.13.0)
29
28
  rspec-mocks (~> 3.13.0)
30
- rspec-core (3.13.0)
29
+ rspec-core (3.13.6)
31
30
  rspec-support (~> 3.13.0)
32
- rspec-expectations (3.13.1)
31
+ rspec-expectations (3.13.5)
33
32
  diff-lcs (>= 1.2.0, < 2.0)
34
33
  rspec-support (~> 3.13.0)
35
- rspec-mocks (3.13.1)
34
+ rspec-mocks (3.13.8)
36
35
  diff-lcs (>= 1.2.0, < 2.0)
37
36
  rspec-support (~> 3.13.0)
38
- rspec-support (3.13.1)
39
- rubocop (1.64.1)
40
- json (~> 2.3)
41
- language_server-protocol (>= 3.17.0)
42
- parallel (~> 1.10)
37
+ rspec-support (3.13.7)
38
+ rubocop (1.92.2)
39
+ json (>= 2.3)
40
+ language_server-protocol (~> 3.17.0.2)
41
+ lint_roller (~> 1.1.0)
42
+ parallel (>= 1.10)
43
43
  parser (>= 3.3.0.2)
44
44
  rainbow (>= 2.2.2, < 4.0)
45
- regexp_parser (>= 1.8, < 3.0)
46
- rexml (>= 3.2.5, < 4.0)
47
- rubocop-ast (>= 1.31.1, < 2.0)
45
+ regexp_parser (>= 2.11.3, < 3.0)
46
+ rubocop-ast (>= 1.49.0, < 2.0)
48
47
  ruby-progressbar (~> 1.7)
49
- unicode-display_width (>= 2.4.0, < 3.0)
50
- rubocop-ast (1.31.3)
51
- parser (>= 3.3.1.0)
48
+ unicode-display_width (>= 2.4.0, < 4.0)
49
+ rubocop-ast (1.50.0)
50
+ parser (>= 3.3.7.2)
51
+ prism (~> 1.7)
52
52
  ruby-progressbar (1.13.0)
53
- simplecov (0.22.0)
54
- docile (~> 1.1)
55
- simplecov-html (~> 0.11)
56
- simplecov_json_formatter (~> 0.1)
57
- simplecov-html (0.12.3)
58
- simplecov_json_formatter (0.1.4)
59
- strscan (3.1.0)
60
- unicode-display_width (2.5.0)
53
+ simplecov (1.3.2)
54
+ unicode-display_width (3.3.0)
55
+ unicode-emoji (~> 4.3)
56
+ unicode-emoji (4.3.0)
61
57
 
62
58
  PLATFORMS
63
59
  ruby
64
60
  x86_64-linux
65
61
 
66
62
  DEPENDENCIES
67
- bundler (~> 2.5.11)
63
+ bundler (~> 4.0)
68
64
  municipitaly2!
69
- rake (~> 13.2.1)
65
+ rake (~> 13.4)
70
66
  rspec (~> 3.13)
71
- rubocop (~> 1.64.1)
72
- simplecov (~> 0.22.0)
67
+ rubocop (~> 1.92)
68
+ simplecov (~> 1.3)
69
+
70
+ CHECKSUMS
71
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
72
+ bundler (4.0.23) sha256=407ba8a1d928f412847f819aa5f8b6aef7c59fb51feb517112af8a165487287b
73
+ csv (3.3.7) sha256=15a3f16f6628da8664d455eb634e7f22031bcf53044923caf56975109e71b9f8
74
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
75
+ json (3.1.0) sha256=3ce7ccf8fde58960177a3a756c31f292a4c1e1dedee884547096a5b0604e3bd8
76
+ language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
77
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
78
+ municipitaly2 (2.0.5)
79
+ parallel (2.3.0) sha256=f75a3e904101ce6a1ccb6b8dc800cbafd42166d83330192438dcf29395167a6f
80
+ parser (3.3.13.0) sha256=e02f9b63c2fe05b0c68f692ba4df89b3cb113b663964f75d988fbebfd6c3deca
81
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
82
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
83
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
84
+ rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
85
+ regexp_parser (2.13.1) sha256=5aedb6b7c35688f51e86eef17a15374dfd287c83f4ca644b2c5f3ec50a33b44b
86
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
87
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
88
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
89
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
90
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
91
+ rubocop (1.92.2) sha256=14fb31eed143a0dc6f78186c550c1715e81cd38f59d05d1165050e445c1f5382
92
+ rubocop-ast (1.50.0) sha256=b9ca88300da0803ee222ad20cdb30494c0a784eed06fdc35d254b06d662788db
93
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
94
+ simplecov (1.3.2) sha256=2a22ec1759f1b8db60881a2e038758956fc69ef93ed669be0bde0678de6d0e85
95
+ unicode-display_width (3.3.0) sha256=4b7aa66a4b11db50f6f7e98411215cd0dd10eaecb665d36eec5bcacb3fa0b613
96
+ unicode-emoji (4.3.0) sha256=11c02fa73290378c066bb0562cd4c87d8e1b706fbbe0059ca12746a4244de8ce
73
97
 
74
98
  BUNDLED WITH
75
- 2.5.11
99
+ 4.0.23
data/README.md CHANGED
@@ -7,13 +7,19 @@ This gem provide various data about 🇮🇹 Italian subdivisions and municipali
7
7
  ## ℹ️️ Informations
8
8
 
9
9
  This gem is a continuation of [Municipitaly by natydev](https://github.com/natydev/municipitaly).
10
- Database is updated up to May 2024 and there are improvements to search.
10
+ Database is updated up to November 2026 and there are improvements to search.
11
11
  Thanks to natydev for the brilliant project.
12
12
 
13
13
  ## 💾 Installation
14
14
 
15
15
  Add this line to your application's Gemfile:
16
16
 
17
+ ```ruby
18
+ gem 'municipitaly2'
19
+ ```
20
+
21
+ or if you want to use directly from the git repo:
22
+
17
23
  ```ruby
18
24
  gem 'municipitaly2', git: 'https://github.com/yupswing/municipitaly2.git', branch: 'master'
19
25
  ```
@@ -248,9 +254,5 @@ The gem is available as open source under the terms of the [MIT License](https:/
248
254
 
249
255
  ## Update database
250
256
 
251
- Check the `tools` folder.
252
- The tool is rought but it gets the job done. Hopefully I will improve it in the future.
253
-
254
- ### Generate vendor/data/municipalities.csv
255
- Update links in `tools/generate.rb` (and/or data in `tools/data/istat*`) and execute
256
- `./tools/generate.rb`
257
+ Check the beginning of the `tools/generate.rb` file to update the sources. Then execute
258
+ `./tools/generate.rb -u -g` (`-u` downloads the sources, `-g` generates the data; run it without arguments for help).
@@ -16,11 +16,17 @@ module Municipitaly2
16
16
  include DataCaller
17
17
 
18
18
  CLASS_METHODS = %i[zone_from_code
19
- region_from_name region_from_istat regions_from_zone_code
20
- province_from_name province_from_istat
21
- province_from_acronym provinces_from_region_istat
22
- provinces_from_zone_code municipalities_from_name
23
- municipality_from_cadastrial municipality_from_istat
19
+ region_from_name
20
+ region_from_istat
21
+ regions_from_zone_code
22
+ province_from_name
23
+ province_from_istat
24
+ province_from_acronym
25
+ provinces_from_region_istat
26
+ provinces_from_zone_code
27
+ municipalities_from_name
28
+ municipality_from_cadastrial
29
+ municipality_from_istat
24
30
  municipalities_from_postal_code
25
31
  municipalities_from_province_istat
26
32
  municipalities_from_region_istat
@@ -118,8 +124,9 @@ module Municipitaly2
118
124
  # example usage:
119
125
  # province = Search.province_from_acronym('MI')
120
126
  def province_from_acronym # :doc:
127
+ acronym = term.strip.upcase
121
128
  data.provinces.find do |p|
122
- p.acronym == term
129
+ p.acronym == acronym
123
130
  end
124
131
  end
125
132
 
@@ -151,6 +158,9 @@ module Municipitaly2
151
158
  # Term can be a partial string and is case insensitive.
152
159
  # The optional parameter +greedy+ [boolean] permit to serch exact term
153
160
  # name (if false) or partial word (true by default).
161
+ # Matches are sorted by relevance: exact matches first, then starting with the
162
+ # term, then words starting with the term, then other matches. Within each
163
+ # group, matches are sorted by population (descending) and then by name.
154
164
  #
155
165
  # example usage:
156
166
  # municipalities = Search.municipalities_from_name('monte')
@@ -161,14 +171,15 @@ module Municipitaly2
161
171
 
162
172
  return [] if term_set.size < 3
163
173
 
164
- regexp = if greedy
165
- Regexp.new(term_set, true)
166
- else
167
- Regexp.new("^#{term_set}$", true)
168
- end
169
- data.municipalities.select do |m|
170
- Municipitaly2.sanitize_term(m.name) =~ regexp || (m.name_alt && Municipitaly2.sanitize_term(m.name_alt) =~ regexp)
171
- end
174
+ # regex per match "greedy" e per match esatto
175
+ exact_re = Regexp.new("^#{term_set}$", true)
176
+ search_re = greedy ? Regexp.new(term_set, true) : exact_re
177
+
178
+ # search results
179
+ matches = filter(data.municipalities, search_re: search_re)
180
+
181
+ # sorts results by relevance
182
+ matches.sort_by { |match| rank(match, term: term_set, exact_re: exact_re, greedy: greedy) }
172
183
  end
173
184
 
174
185
  # returns a +Municipitaly2::Municipality+ object from a <b>cadastrial
@@ -244,5 +255,39 @@ module Municipitaly2
244
255
  istats.include? m.province_istat
245
256
  end
246
257
  end
258
+
259
+ # filters municipalities/provinces (name, name_alt required)
260
+ def filter(list, search_re:)
261
+ list.select do |item|
262
+ name_s = Municipitaly2.sanitize_term(item.name)
263
+ alt_s = item.name_alt && Municipitaly2.sanitize_term(item.name_alt)
264
+ (name_s =~ search_re) || (alt_s && alt_s =~ search_re)
265
+ end
266
+ end
267
+
268
+ # rank municipalities/provinces (name, name_alt, population required)
269
+ def rank(match, term:, exact_re:, greedy: true)
270
+ name_s = Municipitaly2.sanitize_term(match.name)
271
+ alt_s = match.name_alt && Municipitaly2.sanitize_term(match.name_alt)
272
+ names_s = [name_s, alt_s].compact
273
+
274
+ exact_match = names_s.any? { |n| n =~ exact_re }
275
+ any_word_starts = names_s.any? { |n| n.split.any? { |w| w.start_with?(term) } }
276
+
277
+ # Order: 0 = exact, 2 = any word starts, 3 = contains
278
+ priority = if !greedy || exact_match
279
+ 0 # Exact match
280
+ # Disabled because it causes problems in some cases, like putting San Giuliano Milanese after Milazzo
281
+ # elsif names_s.any? { |s| s.start_with?(q) }
282
+ # 1 # Starts with the term
283
+ elsif any_word_starts
284
+ 2 # Any word starts with the term
285
+ else
286
+ 3 # Other (match inside any word)
287
+ end
288
+
289
+ # Priority, population (desc), name (asc)
290
+ [priority, -match.population.to_i, name_s]
291
+ end
247
292
  end
248
293
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Municipitaly2
4
4
  # :nodoc:
5
- VERSION = '2.0.3'
5
+ VERSION = '2.0.5'
6
6
  end
data/lib/municipitaly2.rb CHANGED
@@ -24,6 +24,6 @@ module Municipitaly2
24
24
  # example usage:
25
25
  # sanitized_term = Search.sanitize_term('Forlì Cesena')
26
26
  def self.sanitize_term(term) # :doc:
27
- term.strip.downcase.tr('àâçèéêìòôù', 'aaceeeioou').gsub(/[^a-z]/, '')
27
+ term.strip.downcase.tr('àâçèéêìòôù', 'aaceeeioou').gsub(/[^a-z ]/, '')
28
28
  end
29
29
  end
@@ -32,11 +32,6 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.required_ruby_version = '>= 3.0.0'
34
34
 
35
- spec.add_development_dependency 'bundler', '~> 2.5.11'
36
- spec.add_development_dependency 'rake', '~> 13.2.1'
37
- spec.add_development_dependency 'rspec', '~> 3.13'
38
- spec.add_development_dependency 'rubocop', '~> 1.64.1'
39
- spec.add_development_dependency 'simplecov', '~> 0.22.0'
40
-
35
+ # keep >= to avoid conflicts
41
36
  spec.add_dependency 'csv', '>= 3.3.0' # removed from stdlib in Ruby 3.4
42
37
  end