chilean_cities 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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