woefoo 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in woefoo.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "mocha", "~> 0.9.7"
8
+ gem "shoulda"
9
+ end
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'bundler'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the woefoo gem'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'test'
13
+ t.test_files = FileList['test/**/*_test.rb']
14
+ t.verbose = true
15
+ end
@@ -0,0 +1,22 @@
1
+ module Woefoo
2
+ module Config
3
+ # appid is the user's Yahoo app id (http://developer.yahoo.com/geo/placefinder/)
4
+ attr :appid, true
5
+ # the number of results to return for each request
6
+ attr :placefinder_result_count, true
7
+ # the minimum input quality for a canonical town match
8
+ attr :min_input_quality, true
9
+
10
+ def placefinder_result_count
11
+ (@placefinder_result_count && @placefinder_result_count > 0) ? @placefinder_result_count : 3
12
+ end
13
+
14
+ def min_input_quality
15
+ (@min_input_quality && @min_input_quality > 0) ? @min_input_quality : 40
16
+ end
17
+
18
+ def min_result_quality
19
+ (@min_result_quality && @min_result_quality > 0) ? @min_result_quality : 80
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ module Woefoo
2
+ class GeoplanetAdjacency < ActiveRecord::Base
3
+ set_table_name "geoplanet_adjacencies"
4
+ belongs_to :place, :class_name => 'GeoplanetPlace', :foreign_key => 'woeid', :primary_key => 'woeid'
5
+ belongs_to :adjacent_place, :class_name => 'GeoplanetPlace', :foreign_key => 'neighbour_woeid', :primary_key => 'woeid'
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Woefoo
2
+ class GeoplanetAlias < ActiveRecord::Base
3
+ set_table_name "geoplanet_aliases"
4
+ belongs_to :place,
5
+ :class_name => 'GeoplanetPlace',
6
+ :foreign_key => 'woeid',
7
+ :primary_key => 'woeid'
8
+ end
9
+ end
@@ -0,0 +1,61 @@
1
+ module Woefoo
2
+ class GeoplanetPlace < ActiveRecord::Base
3
+ set_table_name "geoplanet_places"
4
+ set_primary_key 'woeid'
5
+
6
+ has_many :aliases, :class_name => 'GeoplanetAlias', :foreign_key => 'woeid'
7
+ has_many :adjacencies, :class_name => 'GeoplanetAdjacency', :foreign_key => 'woeid'
8
+ has_many :adjacent_places, :through => :adjacencies
9
+
10
+ belongs_to :parent,
11
+ :class_name => "GeoplanetPlace",
12
+ :foreign_key => 'parent_woeid',
13
+ :primary_key => 'woeid'
14
+
15
+ has_ancestry
16
+
17
+ def town
18
+ self.ancestors.find(:first, :conditions => {:place_type => "Town"})
19
+ end
20
+
21
+ def region
22
+ self.ancestors.find(:first, :conditions => {:place_type => "State"})
23
+ end
24
+
25
+ def country
26
+ self.ancestors.find(:first, :conditions => {:place_type => "Country"})
27
+ end
28
+
29
+ def continent
30
+ self.ancestors.find(:first, :conditions => {:place_type => "Continent"})
31
+ end
32
+
33
+ def full_name
34
+ if !@full_name
35
+ @full_name = self.name
36
+ @full_name = "#{@full_name}, #{self.region.name}" if self.region
37
+ @full_name = "#{@full_name}, #{self.country.name}" if self.country
38
+ end
39
+
40
+ return @full_name
41
+ end
42
+
43
+ def full_name_parts
44
+ ret = {:name => self.name}
45
+ ret[:region_name] = self.region.name if self.region
46
+ ret[:country_name] = self.country.name if self.country
47
+ ret[:continent_name] = self.continent.name if self.continent
48
+ return ret
49
+ end
50
+
51
+ def self.build_ancestry_from_parent_ids! parent_id = nil, ancestry = nil
52
+ parent_id = parent_id || 0
53
+ self.base_class.all(:conditions => {:parent_woeid => parent_id}).each do |node|
54
+ node.without_ancestry_callbacks do
55
+ node.update_attribute ancestry_column, ancestry
56
+ end
57
+ build_ancestry_from_parent_ids! node.id, if ancestry.nil? then "#{node.id}" else "#{ancestry}/#{node.id}" end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,53 @@
1
+ require 'nokogiri'
2
+
3
+ module Woefoo
4
+ class Response
5
+ attr_reader :query_options
6
+ attr_reader :typhoeus_response
7
+ attr_reader :xml_doc
8
+ attr_reader :code
9
+ attr_reader :found
10
+ attr_reader :results
11
+ # http://developer.yahoo.com/geo/placefinder/guide/responses.html#address-quality
12
+ attr_reader :input_quality
13
+
14
+ def initialize(opts, response)
15
+ @query_options = opts
16
+ @typhoeus_response = response
17
+ @xml_doc = Nokogiri::XML(response.body)
18
+ @code = response.code
19
+ parse_results!
20
+ end
21
+
22
+
23
+ private
24
+
25
+ # ONLY CALL THIS ONCE!
26
+ def parse_results!
27
+ # woetype => http://developer.yahoo.com/geo/geoplanet/guide/concepts.html#placetypes
28
+ @results = []
29
+ if @xml_doc
30
+ @xml_doc.xpath('ResultSet/Result').each do |r|
31
+ @results << {
32
+ :quality => r.at("quality").text.to_i,
33
+ :line1 => r.at("line1").text,
34
+ :line2 => r.at("line2").text,
35
+ :city => r.at("city").text,
36
+ :state => r.at("state").text,
37
+ :statecode => r.at("statecode").text,
38
+ :postal => r.at("postal").text,
39
+ :countrycode => r.at("countrycode").text,
40
+ :latitude => r.at("latitude").text.to_f,
41
+ :longitude => r.at("longitude").text.to_f,
42
+ :woeid => r.at("woeid").text.to_i,
43
+ :woetype => r.at("woetype").text.to_i
44
+ }
45
+ end
46
+
47
+ @found = @xml_doc.xpath("ResultSet/Found").text.to_i
48
+ @input_quality = @xml_doc.xpath("ResultSet/Quality").text.to_i
49
+ end
50
+ @results.sort! { |x,y| y[:quality] <=> x[:quality] }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,40 @@
1
+ # A town match validator is a hash of two procs, the first proc is
2
+ # a procedure for conditions in which this validator should be used,
3
+ # and the second proc is the actual validator to run on the place results
4
+ require 'geokit'
5
+
6
+ module Woefoo
7
+ module TownMatchValidators
8
+ extend self
9
+
10
+ def default_validators
11
+ [{
12
+ :conditions => Proc.new {|response|
13
+ true # If all else fails, use this catch all validator
14
+ },
15
+ :validator => Proc.new {|response|
16
+ best_match=nil
17
+ if response.input_quality >= min_input_quality
18
+ response.results.each do |r|
19
+ if r[:quality] >= response.input_quality && r[:quality] >= min_result_quality
20
+ place=Woefoo::GeoplanetPlace.find_by_woeid(r[:woeid])
21
+ if place.place_type=="Town"
22
+ # If the query included a country code, make sure the place we're picking is in the same country!
23
+ next if (response.query_options.include?(:country_code) &&
24
+ response.query_options[:country_code].downcase != place.country_code.downcase)
25
+ best_match=r[:woeid]
26
+ elsif ["Zip", "Suburb"].include?(place.place_type) && place.town
27
+ next if (response.query_options.include?(:country_code) &&
28
+ response.query_options[:country_code].downcase != place.country_code.downcase)
29
+ best_match=place.town.woeid
30
+ end
31
+ end
32
+ break if best_match
33
+ end
34
+ end
35
+ best_match
36
+ }
37
+ }]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Woefoo
2
+ VERSION = "0.0.6"
3
+ end
data/lib/woefoo.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'cgi'
2
+ require 'typhoeus'
3
+ require 'active_record'
4
+ require 'ancestry'
5
+ require 'woefoo/config'
6
+ require 'woefoo/town_match_validators'
7
+ require 'woefoo/response'
8
+ require 'woefoo/geoplanet_place'
9
+ require 'woefoo/geoplanet_alias'
10
+ require 'woefoo/geoplanet_adjacency'
11
+
12
+ module Woefoo
13
+ include Woefoo::Config
14
+ include Woefoo::TownMatchValidators
15
+ extend self
16
+ # Fires a placefinder request to yahoo, returns with suggested places that match the query
17
+ def lookup(opts={})
18
+ validate!(opts)
19
+ perform_lookup(opts)
20
+ end
21
+
22
+ # Takes a Woefoo Response, and figures out a Town-level or equivalent
23
+ # woe id that identifies where the queried address is
24
+ def canonical_town_match(response)
25
+ default_validators.each do |v|
26
+ if v[:conditions].call(response)
27
+ return v[:validator].call(response)
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def validate!(opts)
35
+ raise "Woefoo.appid is not defined" if !@appid
36
+ if opts.length == 0 || opts.include?(:query) && (opts[:query] == "")
37
+ raise "Invalid query"
38
+ end
39
+ end
40
+
41
+ def build_query(opts={})
42
+ s = ""
43
+ if opts.include?(:query)
44
+ s = opts[:query]
45
+ else
46
+ [:line1, :city, :region, :zip, :country_code].each do |l|
47
+ s << "#{opts[l]} " if opts.include?(l)
48
+ end
49
+ end
50
+ ::CGI.escape(s)
51
+ end
52
+
53
+ def perform_lookup(opts)
54
+ query = build_query(opts)
55
+ url = "http://where.yahooapis.com/geocode?appid=#{@appid}&count=#{placefinder_result_count}&q=#{query}"
56
+ tr = Typhoeus::Request.get(url)
57
+ Woefoo::Response.new(opts, tr) if tr
58
+ end
59
+ end
@@ -0,0 +1,101 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ResultSet version="1.0">
3
+ <Error>0</Error>
4
+ <ErrorMessage>No error</ErrorMessage>
5
+ <Locale>us_US</Locale>
6
+ <Quality>87</Quality>
7
+ <Found>3</Found>
8
+ <Result>
9
+ <quality>40</quality>
10
+ <latitude>37.416275</latitude>
11
+ <longitude>-122.025092</longitude>
12
+ <offsetlat>37.416397</offsetlat>
13
+ <offsetlon>-122.025055</offsetlon>
14
+ <radius>500</radius>
15
+ <name></name>
16
+ <line1>701 1st Ave</line1>
17
+ <line2>Sunnyvale, CA 94089-1019</line2>
18
+ <line3></line3>
19
+ <line4>United States</line4>
20
+ <house>701</house>
21
+ <street>1st Ave</street>
22
+ <xstreet></xstreet>
23
+ <unittype></unittype>
24
+ <unit></unit>
25
+ <postal>94089-1019</postal>
26
+ <neighborhood></neighborhood>
27
+ <city>Sunnyvale</city>
28
+ <county>Santa Clara County</county>
29
+ <state>California</state>
30
+ <country>United States</country>
31
+ <countrycode>US</countrycode>
32
+ <statecode>CA</statecode>
33
+ <countycode></countycode>
34
+ <uzip>94089</uzip>
35
+ <hash>DDAD1896CC0CDC41</hash>
36
+ <woeid>12797150</woeid>
37
+ <woetype>11</woetype>
38
+ </Result>
39
+ <Result>
40
+ <quality>87</quality>
41
+ <latitude>37.416275</latitude>
42
+ <longitude>-122.025092</longitude>
43
+ <offsetlat>37.416397</offsetlat>
44
+ <offsetlon>-122.025055</offsetlon>
45
+ <radius>500</radius>
46
+ <name></name>
47
+ <line1>701 1st Ave</line1>
48
+ <line2>Sunnyvale, CA 94089-1019</line2>
49
+ <line3></line3>
50
+ <line4>United States</line4>
51
+ <house>701</house>
52
+ <street>1st Ave</street>
53
+ <xstreet></xstreet>
54
+ <unittype></unittype>
55
+ <unit></unit>
56
+ <postal>94089-1019</postal>
57
+ <neighborhood></neighborhood>
58
+ <city>Sunnyvale</city>
59
+ <county>Santa Clara County</county>
60
+ <state>California</state>
61
+ <country>United States</country>
62
+ <countrycode>US</countrycode>
63
+ <statecode>CA</statecode>
64
+ <countycode></countycode>
65
+ <uzip>94089</uzip>
66
+ <hash>DDAD1896CC0CDC41</hash>
67
+ <woeid>12797150</woeid>
68
+ <woetype>11</woetype>
69
+ </Result>
70
+ <Result>
71
+ <quality>80</quality>
72
+ <latitude>37.416275</latitude>
73
+ <longitude>-122.025092</longitude>
74
+ <offsetlat>37.416397</offsetlat>
75
+ <offsetlon>-122.025055</offsetlon>
76
+ <radius>500</radius>
77
+ <name></name>
78
+ <line1>701 1st Ave</line1>
79
+ <line2>Sunnyvale, CA 94089-1019</line2>
80
+ <line3></line3>
81
+ <line4>United States</line4>
82
+ <house>701</house>
83
+ <street>1st Ave</street>
84
+ <xstreet></xstreet>
85
+ <unittype></unittype>
86
+ <unit></unit>
87
+ <postal>94089-1019</postal>
88
+ <neighborhood></neighborhood>
89
+ <city>Sunnyvale</city>
90
+ <county>Santa Clara County</county>
91
+ <state>California</state>
92
+ <country>United States</country>
93
+ <countrycode>US</countrycode>
94
+ <statecode>CA</statecode>
95
+ <countycode></countycode>
96
+ <uzip>94089</uzip>
97
+ <hash>DDAD1896CC0CDC41</hash>
98
+ <woeid>12797150</woeid>
99
+ <woetype>11</woetype>
100
+ </Result>
101
+ </ResultSet>
@@ -0,0 +1,101 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ResultSet version="1.0">
3
+ <Error>0</Error>
4
+ <ErrorMessage>No error</ErrorMessage>
5
+ <Locale>us_US</Locale>
6
+ <Quality>35</Quality>
7
+ <Found>3</Found>
8
+ <Result>
9
+ <quality>40</quality>
10
+ <latitude>37.416275</latitude>
11
+ <longitude>-122.025092</longitude>
12
+ <offsetlat>37.416397</offsetlat>
13
+ <offsetlon>-122.025055</offsetlon>
14
+ <radius>500</radius>
15
+ <name></name>
16
+ <line1>701 1st Ave</line1>
17
+ <line2>Sunnyvale, CA 94089-1019</line2>
18
+ <line3></line3>
19
+ <line4>United States</line4>
20
+ <house>701</house>
21
+ <street>1st Ave</street>
22
+ <xstreet></xstreet>
23
+ <unittype></unittype>
24
+ <unit></unit>
25
+ <postal>94089-1019</postal>
26
+ <neighborhood></neighborhood>
27
+ <city>Sunnyvale</city>
28
+ <county>Santa Clara County</county>
29
+ <state>California</state>
30
+ <country>United States</country>
31
+ <countrycode>US</countrycode>
32
+ <statecode>CA</statecode>
33
+ <countycode></countycode>
34
+ <uzip>94089</uzip>
35
+ <hash>DDAD1896CC0CDC41</hash>
36
+ <woeid>12797150</woeid>
37
+ <woetype>11</woetype>
38
+ </Result>
39
+ <Result>
40
+ <quality>87</quality>
41
+ <latitude>37.416275</latitude>
42
+ <longitude>-122.025092</longitude>
43
+ <offsetlat>37.416397</offsetlat>
44
+ <offsetlon>-122.025055</offsetlon>
45
+ <radius>500</radius>
46
+ <name></name>
47
+ <line1>701 1st Ave</line1>
48
+ <line2>Sunnyvale, CA 94089-1019</line2>
49
+ <line3></line3>
50
+ <line4>United States</line4>
51
+ <house>701</house>
52
+ <street>1st Ave</street>
53
+ <xstreet></xstreet>
54
+ <unittype></unittype>
55
+ <unit></unit>
56
+ <postal>94089-1019</postal>
57
+ <neighborhood></neighborhood>
58
+ <city>Sunnyvale</city>
59
+ <county>Santa Clara County</county>
60
+ <state>California</state>
61
+ <country>United States</country>
62
+ <countrycode>US</countrycode>
63
+ <statecode>CA</statecode>
64
+ <countycode></countycode>
65
+ <uzip>94089</uzip>
66
+ <hash>DDAD1896CC0CDC41</hash>
67
+ <woeid>12797150</woeid>
68
+ <woetype>11</woetype>
69
+ </Result>
70
+ <Result>
71
+ <quality>80</quality>
72
+ <latitude>37.416275</latitude>
73
+ <longitude>-122.025092</longitude>
74
+ <offsetlat>37.416397</offsetlat>
75
+ <offsetlon>-122.025055</offsetlon>
76
+ <radius>500</radius>
77
+ <name></name>
78
+ <line1>701 1st Ave</line1>
79
+ <line2>Sunnyvale, CA 94089-1019</line2>
80
+ <line3></line3>
81
+ <line4>United States</line4>
82
+ <house>701</house>
83
+ <street>1st Ave</street>
84
+ <xstreet></xstreet>
85
+ <unittype></unittype>
86
+ <unit></unit>
87
+ <postal>94089-1019</postal>
88
+ <neighborhood></neighborhood>
89
+ <city>Sunnyvale</city>
90
+ <county>Santa Clara County</county>
91
+ <state>California</state>
92
+ <country>United States</country>
93
+ <countrycode>US</countrycode>
94
+ <statecode>CA</statecode>
95
+ <countycode></countycode>
96
+ <uzip>94089</uzip>
97
+ <hash>DDAD1896CC0CDC41</hash>
98
+ <woeid>12797150</woeid>
99
+ <woetype>11</woetype>
100
+ </Result>
101
+ </ResultSet>
@@ -0,0 +1,39 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ResultSet version="1.0">
3
+ <Error>0</Error>
4
+ <ErrorMessage>No error</ErrorMessage>
5
+ <Locale>us_US</Locale>
6
+ <Quality>87</Quality>
7
+ <Found>1</Found>
8
+ <Result>
9
+ <quality>87</quality>
10
+ <latitude>37.416275</latitude>
11
+ <longitude>-122.025092</longitude>
12
+ <offsetlat>37.416397</offsetlat>
13
+ <offsetlon>-122.025055</offsetlon>
14
+ <radius>500</radius>
15
+ <name></name>
16
+ <line1>701 1st Ave</line1>
17
+ <line2>Sunnyvale, CA 94089-1019</line2>
18
+ <line3></line3>
19
+ <line4>United States</line4>
20
+ <house>701</house>
21
+ <street>1st Ave</street>
22
+ <xstreet></xstreet>
23
+ <unittype></unittype>
24
+ <unit></unit>
25
+ <postal>94089-1019</postal>
26
+ <neighborhood></neighborhood>
27
+ <city>Sunnyvale</city>
28
+ <county>Santa Clara County</county>
29
+ <state>California</state>
30
+ <country>United States</country>
31
+ <countrycode>US</countrycode>
32
+ <statecode>CA</statecode>
33
+ <countycode></countycode>
34
+ <uzip>94089</uzip>
35
+ <hash>DDAD1896CC0CDC41</hash>
36
+ <woeid>12797150</woeid>
37
+ <woetype>11</woetype>
38
+ </Result>
39
+ </ResultSet>
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ class ResponseTest < Test::Unit::TestCase
4
+ TEST_APPID = "asdfjkl"
5
+ COPTER_WORLD_HQ = "103 W. Main Street Charlottesville VA"
6
+ YAHOO_BASE_URL = "http://where.yahooapis.com/geocode"
7
+
8
+ context "results parsing" do
9
+ should "correctly parse results array" do
10
+ typh_resp = mock()
11
+
12
+ typh_resp.expects(:body).returns(File.open(File.join(TEST_DATA_DIR, "single_result.xml")).read)
13
+ typh_resp.expects(:code).returns("200")
14
+
15
+ response = Woefoo::Response.new(COPTER_WORLD_HQ, typh_resp)
16
+
17
+ assert_equal response.code, "200"
18
+ assert_equal response.found, 1
19
+ assert_equal response.results.count, 1
20
+ end
21
+
22
+ should "sort results by quality" do
23
+ typh_resp = mock()
24
+
25
+ typh_resp.expects(:body).returns(File.open(File.join(TEST_DATA_DIR, "multiple_results_1.xml")).read)
26
+ typh_resp.expects(:code).returns("200")
27
+
28
+ response = Woefoo::Response.new(COPTER_WORLD_HQ, typh_resp)
29
+
30
+ assert_equal response.code, "200"
31
+ assert_equal response.found, 3
32
+ assert_equal response.results.count, 3
33
+ assert response.results[0][:quality] > response.results[1][:quality]
34
+ assert response.results[1][:quality] > response.results[2][:quality]
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ dir = File.dirname(File.expand_path(__FILE__))
7
+ $LOAD_PATH.unshift dir + '/../lib'
8
+
9
+ TEST_DATA_DIR = File.join(dir, "data")
10
+ TEST_APPID = "asdfjkl"
11
+ COPTER_WORLD_HQ = "103 W. Main Street Charlottesville VA"
12
+ YAHOO_BASE_URL = "http://where.yahooapis.com/geocode"
13
+
14
+ require 'test/unit'
15
+ require 'shoulda'
16
+ require 'shoulda/context'
17
+ require 'mocha'
18
+ require 'mocha/integration/test_unit'
@@ -0,0 +1,80 @@
1
+ require 'test_helper'
2
+
3
+ class WoefooTest < Test::Unit::TestCase
4
+ context 'lookup exceptions' do
5
+ should "throw an exception if appid is not defined" do
6
+ assert_raises RuntimeError do
7
+ begin
8
+ Woefoo.lookup(COPTER_WORLD_HQ)
9
+ rescue RuntimeError => ex
10
+ assert_equal ex.message, "Woefoo.appid is not defined"
11
+ raise
12
+ end
13
+ end
14
+ end
15
+
16
+ should "throw an exception if the query is nil" do
17
+ assert_raises RuntimeError do
18
+ begin
19
+ Woefoo.appid=TEST_APPID
20
+ Woefoo.lookup
21
+ rescue RuntimeError => ex
22
+ assert ex.message.include?("Invalid query")
23
+ raise
24
+ end
25
+ end
26
+ end
27
+
28
+ should "throw an exception if the query is blank" do
29
+ assert_raises RuntimeError do
30
+ begin
31
+ Woefoo.appid=TEST_APPID
32
+ Woefoo.lookup({:query => ""})
33
+ rescue RuntimeError => ex
34
+ assert ex.message.include?("Invalid query")
35
+ raise
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ context "lookup url generation" do
42
+ should "use default placefinder count if none is defined" do
43
+ typh_resp = Typhoeus::Response.new
44
+ Woefoo.appid=TEST_APPID
45
+ url_should_be="#{YAHOO_BASE_URL}?appid=#{TEST_APPID}&count=3&q=#{::CGI.escape(COPTER_WORLD_HQ)}"
46
+ Typhoeus::Request.expects(:get).with(url_should_be).returns(typh_resp).at_least_once
47
+ Woefoo::Response.expects(:new).with({:query => COPTER_WORLD_HQ}, typh_resp).at_least_once
48
+
49
+ Woefoo.lookup({:query => COPTER_WORLD_HQ})
50
+ end
51
+ end
52
+
53
+ context "canonical town matching" do
54
+ should "not return canonical town result if input quality is below minimum" do
55
+ Woefoo.min_input_quality=50
56
+ response = mock()
57
+ response.expects(:input_quality).returns(35)
58
+ ctr = Woefoo.canonical_town_match(response)
59
+ assert ctr === nil, "No town should match input because input quality was too low"
60
+
61
+ response = mock()
62
+ response.expects(:input_quality).returns(49)
63
+ ctr = Woefoo.canonical_town_match(response)
64
+ assert ctr === nil, "No town should match input because input quality was too low"
65
+ end
66
+
67
+ should "use default validator if no users validators are specified" do
68
+ response = mock()
69
+ place = mock()
70
+ Woefoo::GeoplanetPlace.expects(:find_by_woeid).with(12345).returns(place)
71
+ response.expects(:input_quality).twice.returns(75)
72
+ response.expects(:results).returns([{:quality => 80, :woeid=>12345, :woetype=>7}])
73
+ response.expects(:query_options).returns({})
74
+ place.expects(:place_type).returns("Town")
75
+
76
+ best_woeid = Woefoo.canonical_town_match(response)
77
+ assert_equal 12345, best_woeid, "WOEID town match mismatch!"
78
+ end
79
+ end
80
+ end
data/woefoo.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "woefoo/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "woefoo"
7
+ s.version = Woefoo::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["smnirven"]
10
+ s.email = ["smnirven@gmail.com"]
11
+ s.homepage = "http://smnirven.com"
12
+ s.summary = %q{Lookup yahoo woe (where on earth) ids}
13
+ s.description = %q{Lookup yahoo woe (where on earth) ids}
14
+
15
+ s.rubyforge_project = "woefoo"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency("typhoeus", ">=0.1.27")
23
+ s.add_dependency("nokogiri", ">=1.4.2")
24
+ s.add_dependency("ancestry", ">=1.2.4")
25
+ s.add_dependency("activerecord", ">=2.3.8")
26
+ s.add_dependency("geokit", ">=1.5.0")
27
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: woefoo
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 6
10
+ version: 0.0.6
11
+ platform: ruby
12
+ authors:
13
+ - smnirven
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-25 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: typhoeus
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 45
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 27
34
+ version: 0.1.27
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 2
50
+ version: 1.4.2
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: ancestry
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 23
62
+ segments:
63
+ - 1
64
+ - 2
65
+ - 4
66
+ version: 1.2.4
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 19
78
+ segments:
79
+ - 2
80
+ - 3
81
+ - 8
82
+ version: 2.3.8
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: geokit
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 1
96
+ - 5
97
+ - 0
98
+ version: 1.5.0
99
+ type: :runtime
100
+ version_requirements: *id005
101
+ description: Lookup yahoo woe (where on earth) ids
102
+ email:
103
+ - smnirven@gmail.com
104
+ executables: []
105
+
106
+ extensions: []
107
+
108
+ extra_rdoc_files: []
109
+
110
+ files:
111
+ - .gitignore
112
+ - Gemfile
113
+ - Rakefile
114
+ - lib/woefoo.rb
115
+ - lib/woefoo/config.rb
116
+ - lib/woefoo/geoplanet_adjacency.rb
117
+ - lib/woefoo/geoplanet_alias.rb
118
+ - lib/woefoo/geoplanet_place.rb
119
+ - lib/woefoo/response.rb
120
+ - lib/woefoo/town_match_validators.rb
121
+ - lib/woefoo/version.rb
122
+ - test/data/multiple_results_1.xml
123
+ - test/data/poor_input_quality.xml
124
+ - test/data/single_result.xml
125
+ - test/response_test.rb
126
+ - test/test_helper.rb
127
+ - test/woefoo_test.rb
128
+ - woefoo.gemspec
129
+ has_rdoc: true
130
+ homepage: http://smnirven.com
131
+ licenses: []
132
+
133
+ post_install_message:
134
+ rdoc_options: []
135
+
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ hash: 3
153
+ segments:
154
+ - 0
155
+ version: "0"
156
+ requirements: []
157
+
158
+ rubyforge_project: woefoo
159
+ rubygems_version: 1.5.2
160
+ signing_key:
161
+ specification_version: 3
162
+ summary: Lookup yahoo woe (where on earth) ids
163
+ test_files:
164
+ - test/data/multiple_results_1.xml
165
+ - test/data/poor_input_quality.xml
166
+ - test/data/single_result.xml
167
+ - test/response_test.rb
168
+ - test/test_helper.rb
169
+ - test/woefoo_test.rb