chilean_cities 1.0.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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +674 -0
  4. data/README.md +133 -0
  5. data/Rakefile +43 -0
  6. data/lib/chilean_cities.rb +7 -0
  7. data/lib/chilean_cities/comuna.rb +27 -0
  8. data/lib/chilean_cities/comunas_list.rb +14 -0
  9. data/lib/chilean_cities/factory.rb +46 -0
  10. data/lib/chilean_cities/provincia.rb +23 -0
  11. data/lib/chilean_cities/provincia_part.rb +11 -0
  12. data/lib/chilean_cities/provincias_list.rb +14 -0
  13. data/lib/chilean_cities/region.rb +27 -0
  14. data/lib/chilean_cities/region_part.rb +6 -0
  15. data/lib/chilean_cities/version.rb +3 -0
  16. data/lib/schemas/place.rb +10 -0
  17. data/lib/schemas/thing.rb +6 -0
  18. data/spec/factories/comunas.rb +10 -0
  19. data/spec/factories/provincias.rb +9 -0
  20. data/spec/factories/regiones.rb +10 -0
  21. data/spec/lib/chilean_cities/comuna_spec.rb +67 -0
  22. data/spec/lib/chilean_cities/factory_spec.rb +46 -0
  23. data/spec/lib/chilean_cities/provincia_spec.rb +59 -0
  24. data/spec/lib/chilean_cities/region_spec.rb +66 -0
  25. data/spec/lib/chilean_cities_spec.rb +5 -0
  26. data/spec/spec_helper.rb +35 -0
  27. data/spec/support/factory_girl.rb +18 -0
  28. data/spec/support/schemas/README.md +13 -0
  29. data/spec/support/schemas/spec_for_administrative_area_interface.rb +6 -0
  30. data/spec/support/schemas/spec_for_city_interface.rb +6 -0
  31. data/spec/support/schemas/spec_for_place_interface.rb +14 -0
  32. data/spec/support/schemas/spec_for_state_interface.rb +6 -0
  33. data/spec/support/schemas/spec_for_thing_interface.rb +8 -0
  34. data/spec/support/spec_for_list_of_comunas_interface.rb +22 -0
  35. data/spec/support/spec_for_list_of_provincias_interface.rb +24 -0
  36. data/spec/support/spec_for_part_of_provincia_interface.rb +14 -0
  37. data/spec/support/spec_for_part_of_region_interface.rb +12 -0
  38. metadata +190 -0
@@ -0,0 +1,133 @@
1
+ Comunas de Chile
2
+ ================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/chilean_cities.svg)](http://badge.fury.io/rb/chilean_cities)
5
+ [![Build Status](https://api.travis-ci.org/gonzalo-bulnes/chilean_cities.png?branch=master)](https://travis-ci.org/gonzalo-bulnes/chilean_cities)
6
+ [![Code Climate](https://codeclimate.com/github/gonzalo-bulnes/chilean_cities.png)](https://codeclimate.com/github/gonzalo-bulnes/chilean_cities)
7
+ [![Inline docs](http://inch-ci.org/github/gonzalo-bulnes/chilean_cities.svg?branch=master)](http://inch-ci.org/github/gonzalo-bulnes/chilean_cities)
8
+
9
+ A Ruby representation of the Chilean _administrative areas_ as described by the [SUBDERE][subdere].
10
+
11
+ [subdere]: http://www.subdere.gov.cl
12
+
13
+ Disclaimer
14
+ ----------
15
+
16
+ This library is not developed, supported nor endorsed in any way by the Chilean [Subsecretaría de Desarrollo Regional y Administrativo (SUBDERE)][subdere], nor any related institution.
17
+
18
+ Data Sources
19
+ ------------
20
+
21
+ This library is based on the publicly available information from the SUBDERE related to the [Codificación Única Territorial][source]. The sources quoted by [the document on which this library is based][ref] are:
22
+
23
+ - Decreto Supremo No 1439, del Ministerio del Interior, publicado en el Diario Oficial del 8 de Mayo de 2000
24
+ - Decreto Supremo No 1352, del Ministerio del Interior, publicado en el Diario Oficial del 23 de Agosto de 2008
25
+ - Decreto Exento No 910, del Ministerio del Interior, publicado en el Diario Oficial del 14 de Junio de 2007
26
+ - Decreto Exento No 817, del Ministerio del Interior, publicado en el Diario Oficial del 26 de Marzo de 2010
27
+
28
+ [source]: http://www.subdere.gov.cl/documentacion/regiones-provincias-y-comunas-de-chile
29
+ [ref]: http://www.subdere.gov.cl/sites/default/files/documentos/articles-73111_recurso_2.pdf
30
+
31
+ Usage
32
+ -----
33
+
34
+ Add the gem to your Gemfile:
35
+
36
+ ```ruby
37
+ # Gemfile
38
+
39
+ gem 'chilean_cities', '~> 1.0' # see semver.org
40
+ ```
41
+
42
+ Then generate the chilean administrative areas:
43
+
44
+ ```ruby
45
+ require 'chilean_cities'
46
+
47
+ chile = ChileanCities::Factory.instance
48
+
49
+ chile.generate!
50
+
51
+ # and use them as you want : )
52
+
53
+ chile.regiones.select{ |region| region.iso_3166_2 == 'CL-LL' }.first.name
54
+ # => "Región de los Lagos"
55
+
56
+ chile.provincias.select{ |provincia| provincia.name =~ /Magallanes/ }.first.comunas.map{ |comuna| comuna.name }
57
+ # => ["Punta Arenas", "Laguna Blanca", "Río Verde", "San Gregorio"]
58
+ ```
59
+
60
+ ### Schema.org
61
+
62
+ The generated administrative areas representations do _partially_ enforce the **Place schema** (see [schema.org][schema] and [the schemas specs][schema-specs] for details):
63
+
64
+ ```ruby
65
+ # comunas, provincias and regiones do implement the `contained_in` method:
66
+
67
+ chile.comunas.select{ |comuna| comuna.name == 'Quellón' }.first.contained_in.name
68
+ # => "Chiloé"
69
+ ```
70
+
71
+ [schema]: http://schema.org
72
+ [schema-specs]: spec/support/schemas
73
+
74
+ **Note about the previous version** (`v0.1.0`)
75
+
76
+ If you were using this gem in the past and are looking for its ancient behaviour, please modify your `Gemfile` to checkout the `v0.1.0` tag (it's been a few years, so this is not recommended):
77
+
78
+ ```ruby
79
+ # Gemfile
80
+
81
+ gem 'chilean_cities', git: 'https://github.com/gonzalo-bulnes/chilean_cities.git', tag: 'v0.1.0'
82
+ ```
83
+ The same tag does also [point to the corresponding documentation][deprecated-doc].
84
+
85
+ [deprecated-doc]: https://github.com/gonzalo-bulnes/chilean_cities/blob/v0.1.0/README.md
86
+
87
+ Code of Conduct
88
+ ---------------
89
+
90
+ Please note that by participating in this project, you agree to abide by its [code of conduct]. That is true for pull requests, and also when participating in issues.
91
+
92
+ [code of conduct]: ./CODE_OF_CONDUCT.md
93
+
94
+ See Also
95
+ --------
96
+
97
+ - The Wikipedia article about the [ISO 3166-2][iso] standard
98
+ - Comunas de Chile ([gist][json]) (a Ruby on Rails seed and a JSON document)
99
+ - The Schema.org [AdministrativeArea schema][schema]
100
+ - An interesting overview of [how the administrative areas can be categorized for mapping][administrative_mapping]
101
+ - The [OpenStreetMap relations][osm_boundaries] corresponding to the described administrative areas
102
+
103
+ [iso]: https://en.wikipedia.org/wiki/ISO_3166-2:CL
104
+ [json]: https://gist.github.com/gonzalo-bulnes/337ea1e916e3890fdefa
105
+ [schema]: http://schema.org/AdministrativeArea
106
+ [administrative_mapping]: http://wiki.openstreetmap.org/wiki/Tag:admin%20level=8?uselang=en-US
107
+ [osm_boundaries]: http://www.openstreetmap.org/relation/164609
108
+
109
+ Credits
110
+ -------
111
+
112
+ Part of this gem was crafted during my 10% _free focus_ work time at [Acid Labs][acidlabs]. Thanks @acidlabs!
113
+
114
+ [acidlabs]: https://github.com/acidlabs
115
+
116
+ License
117
+ -------
118
+
119
+ ChileanCities provides a Ruby representation of the Chilean _administrative areas_.
120
+ Copyright (C) 2013, 2020 Gonzalo Bulnes Guilpain
121
+
122
+ This program is free software: you can redistribute it and/or modify
123
+ it under the terms of the GNU General Public License as published by
124
+ the Free Software Foundation, either version 3 of the License, or
125
+ (at your option) any later version.
126
+
127
+ This program is distributed in the hope that it will be useful,
128
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
129
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130
+ GNU General Public License for more details.
131
+
132
+ You should have received a copy of the GNU General Public License
133
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,43 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Provide private interfaces documentation'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ namespace :spec do
10
+ desc 'Provide public interfaces documentation'
11
+ RSpec::Core::RakeTask.new(:public) do |t|
12
+ t.rspec_opts = "--tag public"
13
+ end
14
+ end
15
+
16
+ namespace :spec do
17
+ desc 'Provide private interfaces documentation for development purpose'
18
+ RSpec::Core::RakeTask.new(:development) do |t|
19
+ t.rspec_opts = "--tag protected --tag private"
20
+ end
21
+ end
22
+ rescue LoadError
23
+ desc 'RSpec rake task not available'
24
+ task :spec do
25
+ abort 'RSpec rake task is not available. Be sure to install rspec-core as a gem or plugin'
26
+ end
27
+ end
28
+
29
+ begin
30
+ require 'inch/rake'
31
+
32
+ Inch::Rake::Suggest.new(:inch) do |suggest|
33
+ suggest.args << "--private"
34
+ suggest.args << "--pedantic"
35
+ end
36
+ rescue LoadError
37
+ desc 'Inch rake task not available'
38
+ task :inch do
39
+ abort 'Inch rake task is not available. Be sure to install inch as a gem or plugin'
40
+ end
41
+ end
42
+
43
+ task :default => ['spec:public', 'spec:development', :inch]
@@ -0,0 +1,7 @@
1
+ require 'chilean_cities/version'
2
+ require 'chilean_cities/comuna'
3
+ require 'chilean_cities/provincia'
4
+ require 'chilean_cities/region'
5
+ require 'chilean_cities/factory'
6
+
7
+ module ChileanCities; end
@@ -0,0 +1,27 @@
1
+ require 'active_model'
2
+
3
+ require 'chilean_cities/provincia_part'
4
+ require 'chilean_cities/region_part'
5
+ require 'schemas/place'
6
+
7
+ module ChileanCities
8
+
9
+ class Comuna
10
+ include ActiveModel::Model
11
+
12
+ include ProvinciaPart
13
+ include RegionPart
14
+ include Schemas::Place
15
+
16
+ attr_accessor :code
17
+
18
+ def initialize(*args)
19
+ @name = args.shift
20
+ @code = args.shift
21
+ @provincia = args.shift
22
+ @region = args.shift
23
+ end
24
+
25
+ validates_presence_of :code, :name
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module ChileanCities
2
+ module ComunasList
3
+
4
+ def initialize
5
+ raise NotImplementedError, 'ComunasList must implement initialize()'
6
+ end
7
+
8
+ attr_reader :comunas
9
+
10
+ def append_comuna(comuna)
11
+ @comunas << comuna unless @comunas.include? comuna
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ require 'multi_json'
2
+
3
+ module ChileanCities
4
+
5
+ class Factory
6
+ include Singleton
7
+
8
+ attr_reader :regiones
9
+ attr_reader :provincias
10
+ attr_reader :comunas
11
+
12
+ def generate!
13
+
14
+ @regiones = []
15
+ @provincias = []
16
+ @comunas = []
17
+
18
+ data_file = File.read('data/comunas.json')
19
+
20
+ data = MultiJson.load(data_file, symbolize_keys: true)
21
+
22
+ data.each do |datum|
23
+ comuna = Comuna.new(datum[:name], datum[:code])
24
+
25
+ provincia = @provincias.select { |provincia| provincia.name == datum[:provincia] }.first ||
26
+ Provincia.new(datum[:provincia])
27
+
28
+ region = @regiones.select { |region| region.name == datum[:region] }.first ||
29
+ Region.new(datum[:region], datum[:region_iso_3166_2])
30
+
31
+ comuna.region = region
32
+ comuna.provincia = comuna.contained_in = provincia
33
+ @comunas << comuna unless @comunas.include? comuna
34
+
35
+ provincia.region = provincia.contained_in = region
36
+ provincia.append_comuna(comuna)
37
+ @provincias << provincia unless @provincias.include? provincia
38
+
39
+ region.append_comuna(comuna)
40
+ region.append_provincia(provincia)
41
+ @regiones << region unless @regiones.include? region
42
+ end
43
+ { comunas_count: @comunas.count, provincias_count: @provincias.count, regiones_count: @regiones.count }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_model'
2
+
3
+ require 'chilean_cities/comunas_list'
4
+ require 'chilean_cities/region_part'
5
+
6
+ module ChileanCities
7
+
8
+ class Provincia
9
+ include ActiveModel::Model
10
+
11
+ include ComunasList
12
+ include RegionPart
13
+ include Schemas::Place
14
+
15
+ def initialize(*args)
16
+ @name = args.shift
17
+ @comunas = []
18
+ @region = nil
19
+ end
20
+
21
+ validates_presence_of :name
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module ChileanCities
2
+ module ProvinciaPart
3
+
4
+ def initialize
5
+ raise NotImplementedError, 'ProvinciaPart must implement initialize()'
6
+ @provincia = nil
7
+ end
8
+
9
+ attr_accessor :provincia
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module ChileanCities
2
+ module ProvinciasList
3
+
4
+ def initialize
5
+ raise NotImplementedError, 'ProvinciasList must implement initialize()'
6
+ end
7
+
8
+ attr_reader :provincias
9
+
10
+ def append_provincia(provincia)
11
+ @provincias << provincia unless @provincias.include? provincia
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_model'
2
+
3
+ require 'chilean_cities/comunas_list'
4
+ require 'chilean_cities/provincias_list'
5
+
6
+ module ChileanCities
7
+
8
+ class Region
9
+ include ActiveModel::Model
10
+
11
+ include ComunasList
12
+ include ProvinciasList
13
+ include Schemas::Place
14
+
15
+ attr_accessor :iso_3166_2
16
+
17
+ def initialize(*args)
18
+ @name = args.shift
19
+ @iso_3166_2 = args.shift
20
+ @comunas = []
21
+ @provincias = []
22
+ end
23
+
24
+ validates_presence_of :iso_3166_2, :name
25
+ validates_format_of :iso_3166_2, with: /\ACL-[A-Z][A-Z]\z/ # ISO 3166-2:CL
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ module ChileanCities
2
+ module RegionPart
3
+
4
+ attr_accessor :region
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module ChileanCities
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'schemas/thing'
2
+
3
+ module Schemas
4
+ module Place
5
+ include Schemas::Thing
6
+
7
+ attr_accessor :contained_in
8
+ attr_accessor :has_map
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Schemas
2
+ module Thing
3
+
4
+ attr_accessor :name
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :comuna, class: ChileanCities::Comuna do
3
+ code 15102
4
+ name 'Camarones'
5
+ end
6
+
7
+ factory :invalid_comuna, class: ChileanCities::Comuna do
8
+ # nop
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :provincia, class: ChileanCities::Provincia do
3
+ name 'Arica'
4
+ end
5
+
6
+ factory :invalid_provincia, class: ChileanCities::Provincia do
7
+ # nop
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :region, class: ChileanCities::Region do
3
+ name 'Arica y Parinacota'
4
+ iso_3166_2 'CL-AP'
5
+ end
6
+
7
+ factory :invalid_region, class: ChileanCities::Region do
8
+ # nop
9
+ end
10
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChileanCities::Comuna do
4
+
5
+ describe 'provides a Schema.org interface', public: true do
6
+ it_behaves_like 'a City'
7
+ end
8
+
9
+ it_behaves_like 'part of a ChileanCities::Provincia'
10
+
11
+ it 'responds to :code', public: true do
12
+ expect(subject).to respond_to :code
13
+ end
14
+
15
+ # validations
16
+
17
+ it 'has a valid factory', private: true do
18
+ expect(FactoryGirl.build(:comuna)).to be_valid
19
+ end
20
+
21
+ it 'requires a name', private: true do
22
+ expect(FactoryGirl.build(:comuna, name: nil)).not_to be_valid
23
+ end
24
+
25
+ it 'requires a code', private: true do
26
+ expect(FactoryGirl.build(:comuna, code: nil)).not_to be_valid
27
+ end
28
+
29
+ describe '#provincia', data: true, private: true do
30
+
31
+ it 'returns a ChileanCities::Provincia' do
32
+ chile = ChileanCities::Factory.instance
33
+ chile.generate!
34
+
35
+ subject = chile.comunas.sample
36
+
37
+ expect(subject.provincia).not_to be_nil
38
+ expect(subject.provincia).to be_instance_of ChileanCities::Provincia
39
+ end
40
+ end
41
+
42
+ describe '#region', data: true, private: true do
43
+
44
+ it 'returns a ChileanCities::Region' do
45
+ chile = ChileanCities::Factory.instance
46
+ chile.generate!
47
+
48
+ subject = chile.comunas.sample
49
+
50
+ expect(subject.region).not_to be_nil
51
+ expect(subject.region).to be_instance_of ChileanCities::Region
52
+ end
53
+ end
54
+
55
+ describe '#contained_in', data: true, private: true do
56
+
57
+ it 'returns a ChileanCities::Provincia' do
58
+ chile = ChileanCities::Factory.instance
59
+ chile.generate!
60
+
61
+ subject = chile.comunas.sample
62
+
63
+ expect(subject.contained_in).not_to be_nil
64
+ expect(subject.contained_in).to be_instance_of ChileanCities::Provincia
65
+ end
66
+ end
67
+ end