04 ottobre 2009

Province e Comuni in Rails

Il molte web application e' molto utile poter selezionionare regione, provincia e comune mediante combo o list box.
In Rails per poter caricare la lista delle citta in una list box e' ideale avere i dati presenti nel database ed accessibili mediante un modello.

In questo post descrivo come popolare il database con i nomi delle province e dei comuni italiani.
Ho trascurato le regioni, il procedimento e' tuttavia molto simile.

Il primo passo e' scaricare la lista dei dati da importare, cioe' le liste dei nomi dei comuni e province.
Queste si trovano nel sito ISTAT in formato CVS:
- Elenco dei comuni (elenco_comuni_italiani_30_giugno_2009.csv)
- Ripartizioni, province e regioni (ripartizioni_regioni_province.csv)
Salviamoli in /lib/tasks (o la directory che preferite).

Bisogna adesso editare entrambi i file, ed eliminare le prime righe (ed ultime) contententi intestazioni e descrizioni.
Il codice che eseguiremo non effettua infatti controlli sulla validita' delle linee, quelle che non contengono i dati vanno quindi eliminate.

Creiamo adesso i 2 modelli:
- City che conterra' le province
- Municipality conterra' i comuni.
Usiamo script/generate dalla linea di comando:
script/generate model city name:string
script/generate model municipality name:string city_id:integer

tali comandi hanno inoltre generato due migration file (create_cities e create_municipalities).
Aggiorniamo (forse e' piu' adatto il termine migriamo) il db con il comando rake:

rake db:migration

Dato che ogni provincia(City) ha molti comuni (Municipalities), ed ogni comune appartiene ad una provincia, aggiorniamo i due modelli come segue:

class City < face="courier new">desso occupiamoci della parte piu' interessante: il caricamento dei dati nel database. Creiamo un nuovo task file nella directory lib/tasks. In tale file aggiungeremo il task che si occupa di popolare il DB, chiamiamolo quindi populate.rake .
Ecco il codice da inserire nel file:

namespace :db do
desc "Load all Italian's cities"
task :load_cities => :environment do
[City, Municipality].each(&:delete_all)
File.open(Dir.pwd + '/lib/tasks/ripartizioni_regioni_province.csv', 'r') do |f|
while line = f.gets
data = line.split ';'
puts 'Code ' + data[8] + ' - City ' + data[10]
city = City.new do |c|
c.id = data[8].to_i
c.name = data[10]
end
city.save
end
end
File.open(Dir.pwd + '/lib/tasks/elenco_comuni_italiani_30_giugno_2009.csv', 'r') do |f|
while line = f.gets
data = line.split ';'
#puts data.inspect
puts 'City Code ' + data[1] + ' - Municipality ' + data[8]
Municipality.create(:city_id => data[1].to_i, :name => data[8])
end
end
end
end

Il codice e' semplice. Per comprenderlo piu' rapidamente basta notare che:
- i file csv sono file testo separati da punto e virgola ;
- i nomi delle province si trovano nella undicesima colonna di ripartizioni_regioni_province.csv (vedi "c.name = data[10]")
- i nomi dei comuni si trovano nella seconda colonna di elenco_comuni_italiani_30_giugno_2009.csv (vedi ":name => data[8]")
- il campo city_id e' la chiave esterna che indica la provincia del comune, questo viene popolato con il codice ISTAT della provincia, cos'i' come il campo id della tabella cities.

Adesso non rimane che eseguirlo:

rake db:load_cities

ed aspettare qualche secondo il completamento del caricamento dei dati nel database.

Il gioco e' fatto !
Possiamo adesso usare i modelli City e Municipality per accedere ai dati.
Testiamo il loro funzionamento tramite script/console:

>> comuni_catania = City.find_by_name("Catania").municipalities
fornira' tutti i comuni della provincia di Catania

>> provincia = Municipality.find_by_name("Aci Castello").city
fornira' la provincia di Aci Castello, cioe' Catania

Adesso potete utilizzare Comuni e Province in tutte le vostre rails application !
Segnalatemi pure soluzioni alternative o eventuali errori.

Nessun commento:

Posta un commento