source: subversion/sites/rails_port/app/controllers/geocoder_controller.rb @ 2659

Revision 2659, 4.8 KB checked in by nickb, 7 years ago (diff)

Fixed up name search and postcode search

Line 
1class GeocoderController < ApplicationController
2  layout 'site'
3
4  require 'net/http'
5  require 'rexml/document'
6
7  def search
8    @postcode_arr = []
9
10    unless params[:query][:postcode].empty?
11      postcode = params[:query][:postcode].upcase
12      escaped_postcode = postcode.sub(/\s/,'%20')
13
14      if postcode.match(/(^\d{5}$)|(^\d{5}-\d{4}$)/)
15        # Its a zip code - ask geocoder.us
16        # (They have a non commerical use api)
17        Net::HTTP.start('rpc.geocoder.us') do |http|
18          resp = http.get("/service/csv?zip=#{postcode}")
19          if resp.body.match(/couldn't find this zip/)
20            redirect_to "/index.html?error=invalid_zip_code"
21            return
22          end
23          data = resp.body.split(/, /) # lat,long,town,state,zip
24          lat = data[0] 
25          lon = data[1]
26          redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
27          return
28        end
29      elsif postcode.match(/^([A-Z]{1,2}\d+[A-Z]?\s*\d[A-Z]{2})/)
30        # It matched our naive UK postcode regexp
31        # Ask npemap to do a combined npemap + freethepostcode search
32        Net::HTTP.start('www.npemap.org.uk') do |http|
33          resp = http.get("/cgi/geocoder.fcgi?format=text&postcode=#{escaped_postcode}")
34          dataline = resp.body.split(/\n/)[1]
35          data = dataline.split(/,/) # easting,northing,postcode,lat,long
36          lat = data[3] 
37          lon = data[4]
38          redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
39          return
40        end
41      elsif postcode.match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d/)
42        # It's a canadian postcode
43        # Ask geocoder.ca (note - they have a per-day limit)
44        postcode = postcode.sub(/\s/,'')
45        Net::HTTP.start('geocoder.ca') do |http|
46          resp = http.get("?geoit=XML&postal=#{postcode}")
47          data_lat = resp.body.slice(/latt>.*?</)
48          data_lon = resp.body.slice(/longt>.*?</)
49          lat = data_lat.split(/[<>]/)[1]
50          lon = data_lon.split(/[<>]/)[1]
51          redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
52          return
53        end
54      elsif postcode.match(/(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})
55        /)
56        #its a UK postcode
57        begin
58          Net::HTTP.start('www.freethepostcode.org') do |http|
59            resp = http.get("/geocode?postcode=#{postcode}")
60            lat = resp.body.scan(/[4-6][0-9]\.?[0-9]+/)
61            lon = resp.body.scan(/[-+][0-9]\.?[0-9]+/)
62            redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
63            return
64          end
65        rescue
66          redirect_to "/index.html"
67          #redirect to somewhere else
68        end
69        redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
70        #redirect_to "/index.html?error=unknown_postcode_or_zip"
71      elsif
72        # Some other postcode / zip code
73        # Throw it at geonames, and see if they have any luck with it
74        Net::HTTP.start('ws.geonames.org') do |http|
75          resp = http.get("/postalCodeSearch?postalcode=#{escaped_postcode}&maxRows=1")
76          hits = resp.body.slice(/totalResultsCount>.*?</).split(/[<>]/)[1]
77          if hits == "0"
78            # Geonames doesn't know, it's probably wrong
79            redirect_to "/index.html?error=unknown_postcode_or_zip"
80            return
81          end
82          data_lat = resp.body.slice(/lat>.*?</)
83          data_lon = resp.body.slice(/lng>.*?</)
84          lat = data_lat.split(/[<>]/)[1]
85          lon = data_lon.split(/[<>]/)[1]
86          redirect_to "/index.html?lat=#{lat}&lon=#{lon}&zoom=14"
87        end
88      else
89        # Some other postcode / zip file
90        redirect_to "/index.html?error=unknown_postcode_or_zip"
91        return
92      end
93    end
94
95    if params[:query][:place_name] 
96      @place_name = params[:query][:place_name]
97      redirect_to :controller => 'geocoder', :action => 'results', :params => {:place_name => @place_name}
98    end 
99  end
100
101  def results
102    @place_name = params[:place_name]
103    res_hash = {}
104    @res_ary = []
105    begin
106      Net::HTTP.start('ws.geonames.org') do |http|
107        res = http.get("/search?q=#{@place_name}&maxRows=10")
108        xml = REXML::Document.new(res.body)
109        xml.elements.each("geonames/geoname") do |ele|
110          res_hash = {}
111          ele.elements.each("name"){ |n| res_hash['name'] = n.text }
112          ele.elements.each("countryCode"){ |n| res_hash['countrycode'] = n.text }
113          ele.elements.each("countryName"){ |n| res_hash['countryname'] = n.text }
114          ele.elements.each("lat"){ |n| res_hash['lat'] = n.text }
115          ele.elements.each("lng"){ |n| res_hash['lon']= n.text }
116          @res_ary << res_hash
117        end 
118      end
119    rescue
120      #Flash a notice to say that geonames is broken
121      redirect_to "/index.html"
122    end
123  end
124end
Note: See TracBrowser for help on using the repository browser.