Class: Graticule::Geocoder::Multi

Inherits:
Object
  • Object
show all
Defined in:
lib/graticule/geocoder/multi.rb

Instance Method Summary collapse

Constructor Details

#initialize(*geocoders, &acceptable) ⇒ Multi

The Multi geocoder allows you to use multiple geocoders in succession.

geocoder = Graticule.service(:multi).new(
  Graticule.service(:google).new("api_key"),
  Graticule.service(:yahoo).new("api_key"),
)
geocoder.locate '49423' # <= tries geocoders in succession

The Multi geocoder will try the geocoders in order if a Graticule::AddressError is raised. You can customize this behavior by passing in a block to the Multi geocoder. For example, to try the geocoders until one returns a result with a high enough precision:

geocoder = Graticule.service(:multi).new(geocoders) do |result|
  result.precision >= Graticule::Precision.street
end

Geocoders will be tried in order until the block returned true for one of the results



24
25
26
27
# File 'lib/graticule/geocoder/multi.rb', line 24

def initialize(*geocoders, &acceptable)
  @acceptable = acceptable || lambda { true }
  @geocoders = geocoders.flatten
end

Instance Method Details

#locate(*args) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/graticule/geocoder/multi.rb', line 29

def locate(*args)
  mode, address = nil, nil
  case args.first
  when :first
    mode = :first
    address = args[1]
  when :all
    mode = :all
    address = args[1]
  else
    mode = :first
    address = args.first
  end

  locations = Locations.new
  last_error = nil

  catch :found_first do
    @geocoders.each do |geocoder|
      begin
        geocoder_locations = geocoder.locate(:all, address)

        geocoder_locations.each do |location|
          if(@acceptable.call(location))
            locations << location

            if(mode == :first)
              throw :found_first
            end
          end
        end
      rescue Errno::ECONNREFUSED
        logger.error("Connection refused to #{service}")
      rescue Error => e
        last_error = e
      end
    end
  end

  if(mode == :first)
    if(locations.first)
      locations.first
    else
      raise last_error || AddressError.new("Couldn't find '#{address}' with any of the services")
    end
  else
    locations
  end
end