Class: Geogov::GeoStack

Inherits:
Object
  • Object
show all
Defined in:
lib/geogov/geo_stack.rb

Constant Summary collapse

LOCALITY_KEYS =

Key to the three-letter abbreviations CTY | County CED | County Electoral Division DIS | District DIW | District Ward EUR | European Region GLA | Greater London Authority LAC | Greater London Authority Assembly Constituency LBR | London Borough LBW | London Borough Ward MTD | Metropolitan District MTW | Metropolitan District Ward SPE | Scottish Parliament Electoral Region SPC | Scottish Parliament Constituency UTA | Unitary Authority UTE | Unitary Authority Electoral Division UTW | Unitary Authority Ward WAE | Welsh Assembly Electoral Region WAC | Welsh Assembly Constituency WMC | Westminster Constituency LGW | NI Ward LGD | NI Council LGE | NI Electoral Area NIE | NI Assembly Constituency NIA | NI Assembly

[
  [:LBO],       # London (special case)
  [:DIS, :CTY],
  [:CPC, :UTA], # Cornwall civil parishes
  [:UTE, :UTA],
  [:UTW, :UTA],
  [:MTW, :MTD],
  [:LGW, :LGD]
]
UK_NATIONS =
['England', 'Scotland', 'Northern Ireland', 'Wales']
POSTCODE_REGEXP =
/^([A-Z]{1,2}[0-9R][0-9A-Z]?)\s*([0-9])[ABD-HJLNP-UW-Z]{2}(:?\s+)?$/i
SECTOR_POSTCODE_REGEXP =
/^([A-Z]{1,2}[0-9R][0-9A-Z]?)\s*([0-9])(:?\s+)?$/i

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ GeoStack

Returns a new instance of GeoStack.



7
8
9
10
11
12
13
14
# File 'lib/geogov/geo_stack.rb', line 7

def initialize(&block)
  if block_given?
    yield self
    raise ArgumentError, "fuzzy point required" unless fuzzy_point
  else
    self.fuzzy_point = calculate_fuzzy_point
  end
end

Instance Attribute Details

#authoritiesObject

Returns the value of attribute authorities.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def authorities
  @authorities
end

#councilObject

Returns the value of attribute council.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def council
  @council
end

#countryObject

Returns the value of attribute country.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def country
  @country
end

#fuzzy_pointObject

Returns the value of attribute fuzzy_point.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def fuzzy_point
  @fuzzy_point
end

#latObject

Returns the value of attribute lat.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def lat
  @lat
end

#lonObject

Returns the value of attribute lon.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def lon
  @lon
end

#nationObject

Returns the value of attribute nation.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def nation
  @nation
end

#postcodeObject

Returns the value of attribute postcode.



5
6
7
# File 'lib/geogov/geo_stack.rb', line 5

def postcode
  @postcode
end

#regionObject

Returns the value of attribute region.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def region
  @region
end

#wardObject

Returns the value of attribute ward.



4
5
6
# File 'lib/geogov/geo_stack.rb', line 4

def ward
  @ward
end

Class Method Details

.new_from_hash(hash) ⇒ Object



47
48
49
# File 'lib/geogov/geo_stack.rb', line 47

def self.new_from_hash(hash)
  new { |gs| gs.set_fields hash }
end

.new_from_ip(ip_address) ⇒ Object



39
40
41
42
43
44
45
# File 'lib/geogov/geo_stack.rb', line 39

def self.new_from_ip(ip_address)
  remote_location = Geogov.remote_location(ip_address)
  new { |gs|
    gs.country = remote_location['country'] if remote_location
    gs.fuzzy_point = gs.calculate_fuzzy_point
  }
end

Instance Method Details

#build_localityObject



129
130
131
132
133
134
135
136
137
138
# File 'lib/geogov/geo_stack.rb', line 129

def build_locality
  return false unless authorities
  selected_keys = LOCALITY_KEYS.find { |t|
    (t - authorities.keys).none?
  } or return false

  parts = selected_keys.map { |a| formatted_authority_name(a) }
  parts << "London" if selected_keys == [:LBO]
  parts.uniq.join(", ")
end

#calculate_fuzzy_pointObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/geogov/geo_stack.rb', line 16

def calculate_fuzzy_point
  if lat && lon
    return FuzzyPoint.new(lat, lon, :point)
  end

  if postcode
    district = postcode.split(" ")[0]
    district_centre = Geogov.centre_of_district(district)
    if district_centre
      return FuzzyPoint.new(district_centre["lat"], district_centre["lon"],:postcode_district)
    end
  end

  if country
    country_centre = Geogov.centre_of_country(country)
    if country_centre
      return FuzzyPoint.new(country_centre["lat"], country_centre["lon"],:country)
    end
  end

  FuzzyPoint.new(0,0,:planet)
end

#fetch_missing_fields_for_coords(lat, lon) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/geogov/geo_stack.rb', line 157

def fetch_missing_fields_for_coords(lat, lon)
  fields = Geogov.areas_for_stack_from_coords(lat, lon)
  if UK_NATIONS.include?(fields[:nation])
    self.country = 'UK'
    set_fields fields.select { |k,v| k != :point }
  end
end

#fetch_missing_fields_for_postcode(postcode) ⇒ Object



144
145
146
147
148
149
150
151
152
153
# File 'lib/geogov/geo_stack.rb', line 144

def fetch_missing_fields_for_postcode(postcode)
  if matches = postcode.match(POSTCODE_REGEXP)
    self.country = "UK"
    fields = Geogov.areas_for_stack_from_postcode(postcode)
    if fields
      lat_lon = fields[:point]
      set_fields fields.select { |k,v| k != :point }
    end
  end
end

#formatted_authority_name(type) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/geogov/geo_stack.rb', line 83

def formatted_authority_name(type)
  authority = get_authority(type) or return type

  authority["name"].gsub(%r{
    \s*((((District|Borough|County|City)\s|)Council|Community)\s?)+ |
    \s(North|East|South|West|Central)$ |
    Mid\s
  }x, "")
end

#friendly_nameObject



75
76
77
# File 'lib/geogov/geo_stack.rb', line 75

def friendly_name
  @friendly_name ||= build_locality
end

#get_authority(type) ⇒ Object



79
80
81
# File 'lib/geogov/geo_stack.rb', line 79

def get_authority(type)
  authorities[type.upcase.to_sym]
end

#has_valid_lat_lon(hash) ⇒ Object



140
141
142
# File 'lib/geogov/geo_stack.rb', line 140

def has_valid_lat_lon(hash)
  %w[ lat lon ].none? { |k| hash[k].to_s.empty? }
end

#set_fields(hash) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/geogov/geo_stack.rb', line 165

def set_fields(hash)
  hash.each do |geo, value|
    setter = "#{geo.to_s}=".to_sym
    if respond_to?(setter)
      self.send(setter, value) unless value == ""
    else
      self.authorities ||= {}
      self.authorities[geo] = value
    end
  end
  self
end

#to_hashObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/geogov/geo_stack.rb', line 51

def to_hash
  {
    :fuzzy_point   => fuzzy_point.to_hash,
    :postcode      => postcode,
    :council       => council,
    :ward          => ward,
    :friendly_name => friendly_name,
    :nation        => nation
  }
end

#update(hash) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/geogov/geo_stack.rb', line 62

def update(hash)
  self.class.new do |empty|
    full_postcode = hash['postcode']
    empty.set_fields hash
    if has_valid_lat_lon(hash)
      empty.fetch_missing_fields_for_coords(hash['lat'], hash['lon'])
    elsif full_postcode
      empty.fetch_missing_fields_for_postcode(full_postcode)
    end
    empty.fuzzy_point = empty.calculate_fuzzy_point
  end
end