technicalpickles-daywalker 0.1.0
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/README.rdoc +39 -0
- data/VERSION.yml +4 -0
- data/lib/daywalker.rb +23 -0
- data/lib/daywalker/base.rb +22 -0
- data/lib/daywalker/district.rb +43 -0
- data/lib/daywalker/dynamic_finder_match.rb +23 -0
- data/lib/daywalker/legislator.rb +144 -0
- data/lib/daywalker/type_converter.rb +91 -0
- data/spec/daywalker/district_spec.rb +105 -0
- data/spec/daywalker/dynamic_finder_match_spec.rb +33 -0
- data/spec/daywalker/legislator_spec.rb +204 -0
- data/spec/daywalker/type_converter_spec.rb +215 -0
- data/spec/daywalker_spec.rb +4 -0
- data/spec/fixtures/districts_by_latlng.xml +7 -0
- data/spec/fixtures/districts_by_latlng_bad_api.xml +8 -0
- data/spec/fixtures/districts_by_latlng_missing_lat.xml +9 -0
- data/spec/fixtures/districts_by_zip.xml +7 -0
- data/spec/fixtures/districts_by_zip_bad_api.xml +8 -0
- data/spec/fixtures/districts_by_zip_missing_zip.xml +9 -0
- data/spec/fixtures/legislators_by_zip.xml +7 -0
- data/spec/fixtures/legislators_by_zip_bad_api.xml +8 -0
- data/spec/fixtures/legislators_find_by_ny_district_4.xml +7 -0
- data/spec/fixtures/legislators_find_by_ny_district_4_bad_api.xml +8 -0
- data/spec/fixtures/legislators_find_ny_senators.xml +7 -0
- data/spec/fixtures/legislators_find_ny_senators_bad_api.xml +8 -0
- data/spec/spec_helper.rb +21 -0
- metadata +82 -0
data/README.rdoc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= daywalker
|
2
|
+
|
3
|
+
A Ruby wrapper for the Sunlight Labs API: http://wiki.sunlightlabs.com/Sunlight_API_Documentation
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
# Run the following if you haven't already:
|
8
|
+
gem sources -a http://gems.github.com
|
9
|
+
# Install the gem(s):
|
10
|
+
sudo gem install technicalpickles-daywalke
|
11
|
+
|
12
|
+
== Get an API key
|
13
|
+
|
14
|
+
Before starting you need to register for an API key: http://services.sunlightlabs.com/api/register/
|
15
|
+
|
16
|
+
After registering, you will receive an email prompting you to activate the API key.
|
17
|
+
|
18
|
+
== Examples
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
require 'daywalker'
|
22
|
+
require 'pp'
|
23
|
+
|
24
|
+
Daywalker.api_key = 'this is so sekrit'
|
25
|
+
|
26
|
+
pp Daywalker::District.find_by_zip('27511')
|
27
|
+
pp Daywalker::District.find_by_latlng(40.739157, -73.990929)
|
28
|
+
pp Daywalker::Legislator.find(:one, :state => 'NY', :district => 4)
|
29
|
+
pp Daywalker::Legislator.find_all_by_state_and_senator('NY', :senator)
|
30
|
+
|
31
|
+
|
32
|
+
== FAQ
|
33
|
+
|
34
|
+
Q:: Why not use the existing gem, available at http://github.com/luigi/sunlight/tree/master ?
|
35
|
+
A:: Mostly, I didn't have a good experience when just poking around the Sunlight Labs API. I was dense and didn't activate my API key at first, but it didn't notice that. Even after activating, I wasn't getting any data back.
|
36
|
+
|
37
|
+
== COPYRIGHT
|
38
|
+
|
39
|
+
Copyright (c) 2009 Josh Nichols. See LICENSE for details.
|
data/VERSION.yml
ADDED
data/lib/daywalker.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'happymapper'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
require 'daywalker/base'
|
5
|
+
require 'daywalker/type_converter'
|
6
|
+
require 'daywalker/dynamic_finder_match'
|
7
|
+
require 'daywalker/district'
|
8
|
+
require 'daywalker/legislator'
|
9
|
+
|
10
|
+
module Daywalker
|
11
|
+
# Set the API to be used
|
12
|
+
def self.api_key=(api_key)
|
13
|
+
@api_key = api_key
|
14
|
+
end
|
15
|
+
# Get the API to be used
|
16
|
+
def self.api_key
|
17
|
+
@api_key
|
18
|
+
end
|
19
|
+
|
20
|
+
# Error for when you use the API with a bad API key
|
21
|
+
class BadApiKey < StandardError
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Daywalker
|
2
|
+
class Base # :nodoc:
|
3
|
+
include HTTParty
|
4
|
+
base_uri 'http://services.sunlightlabs.com/api'
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def self.handle_response(response)
|
9
|
+
case response.code.to_i
|
10
|
+
when 403 then raise BadApiKey
|
11
|
+
when 200 then parse(response.body)
|
12
|
+
|
13
|
+
when 400 then handle_bad_request(response.body)
|
14
|
+
else raise "Don't know how to handle code #{response.code.inspect}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.handle_bad_request(body)
|
19
|
+
raise "Don't know how to handle #{body.inspect}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Daywalker
|
2
|
+
# Represents a Congressional district.
|
3
|
+
#
|
4
|
+
# They have the following attributes:
|
5
|
+
# * number
|
6
|
+
# * state (as a two-letter abbreviation)
|
7
|
+
class District < Base
|
8
|
+
include HappyMapper
|
9
|
+
|
10
|
+
tag 'district'
|
11
|
+
element 'number', Integer
|
12
|
+
element 'state', String
|
13
|
+
|
14
|
+
# Find districts by latitude and longitude.
|
15
|
+
def self.find_by_latlng(lat, lng)
|
16
|
+
# TODO use ArgumentError
|
17
|
+
raise(ArgumentError, 'missing required parameter latitude') if lat.nil?
|
18
|
+
|
19
|
+
query = {
|
20
|
+
:latitude => lat,
|
21
|
+
:longitude => lng,
|
22
|
+
:apikey => Daywalker.api_key
|
23
|
+
}
|
24
|
+
response = get('/districts.getDistrictFromLatLong.xml', :query => query)
|
25
|
+
handle_response(response) # TODO should only ever return one?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Find districts by zip code
|
29
|
+
def self.find_by_zip(zip)
|
30
|
+
# TODO use ArgumentError
|
31
|
+
raise(ArgumentError, 'missing required parameter zip') if zip.nil?
|
32
|
+
|
33
|
+
query = {
|
34
|
+
:zip => zip,
|
35
|
+
:apikey => Daywalker.api_key
|
36
|
+
}
|
37
|
+
response = get('/districts.getDistrictsFromZip.xml', :query => query)
|
38
|
+
|
39
|
+
handle_response(response)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Daywalker
|
2
|
+
|
3
|
+
class DynamicFinderMatch # :nodoc:
|
4
|
+
attr_accessor :finder, :attribute_names
|
5
|
+
def initialize(method)
|
6
|
+
case method.to_s
|
7
|
+
when /^find_(all_by|by)_([_a-zA-Z]\w*)$/
|
8
|
+
@finder = case $1
|
9
|
+
when 'all_by' then :all
|
10
|
+
when 'by' then :one
|
11
|
+
end
|
12
|
+
@attribute_names = $2.split('_and_').map {|each| each.to_sym}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def match?
|
17
|
+
@attribute_names && @attribute_names.all? do |each|
|
18
|
+
Daywalker::Legislator::VALID_ATTRIBUTES.include? each
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Daywalker
|
2
|
+
# Represents a legislator, either a Senator or Representative.
|
3
|
+
#
|
4
|
+
# They have the following attributes:
|
5
|
+
# * district_number
|
6
|
+
# * title (ether :senator or :representative)
|
7
|
+
# * eventful_id (on http://eventful.com)
|
8
|
+
# * in_office (true or false)
|
9
|
+
# * state (two-letter abbreviation)
|
10
|
+
# * votesmart_id (on http://www.votesmart.org)
|
11
|
+
# * party (:democrat, :republican, or :independent)
|
12
|
+
# * crp_id (on http://opensecrets.org)
|
13
|
+
# * website_url
|
14
|
+
# * fax_number
|
15
|
+
# * govtrack_id (on http://www.govtrack.us)
|
16
|
+
# * first_name
|
17
|
+
# * middle_name
|
18
|
+
# * last_name
|
19
|
+
# * congress_office (address in Washington, DC)
|
20
|
+
# * bioguide_id (on http://bioguide.congress.gov)
|
21
|
+
# * webform_url
|
22
|
+
# * youtube_url
|
23
|
+
# * nickname
|
24
|
+
# * phone
|
25
|
+
# * fec_id (on http://fec.gov)
|
26
|
+
# * gender (:male or :female)
|
27
|
+
# * name_suffix
|
28
|
+
# * twitter_id (on http://twitter.com)
|
29
|
+
# * congresspedia_url
|
30
|
+
class Legislator < Base
|
31
|
+
include HappyMapper
|
32
|
+
|
33
|
+
tag 'legislator'
|
34
|
+
element 'district_number', Integer, :tag => 'district'
|
35
|
+
element 'title', TypeConverter, :parser => :title_abbr_to_sym
|
36
|
+
element 'eventful_id', String
|
37
|
+
element 'in_office', Boolean
|
38
|
+
element 'state', String
|
39
|
+
element 'votesmart_id', Integer
|
40
|
+
element 'official_rss_url', TypeConverter, :tag => 'official_rss', :parser => :blank_to_nil
|
41
|
+
element 'party', TypeConverter, :parser => :party_letter_to_sym
|
42
|
+
element 'email', TypeConverter, :parser => :blank_to_nil
|
43
|
+
element 'crp_id', String
|
44
|
+
element 'website_url', String, :tag => 'website'
|
45
|
+
element 'fax_number', String, :tag => 'fax'
|
46
|
+
element 'govtrack_id', Integer
|
47
|
+
element 'first_name', String, :tag => 'firstname'
|
48
|
+
element 'middle_name', String, :tag => 'middlename'
|
49
|
+
element 'last_name', String, :tag => 'lastname'
|
50
|
+
element 'congress_office', String
|
51
|
+
element 'bioguide_id', String
|
52
|
+
element 'webform_url', String, :tag => 'webform'
|
53
|
+
element 'youtube_url', String
|
54
|
+
element 'nickname', TypeConverter, :parser => :blank_to_nil
|
55
|
+
element 'phone', String
|
56
|
+
element 'fec_id', String
|
57
|
+
element 'gender', TypeConverter, :parser => :gender_letter_to_sym
|
58
|
+
element 'name_suffix', TypeConverter, :parser => :blank_to_nil
|
59
|
+
element 'twitter_id', TypeConverter, :parser => :blank_to_nil
|
60
|
+
element 'sunlight_old_id', String
|
61
|
+
element 'congresspedia_url', String
|
62
|
+
|
63
|
+
VALID_ATTRIBUTES = [:district_number, :title, :eventful_id, :in_office, :state, :votesmart_id, :official_rss_url, :party, :email, :crp_id, :website_url, :fax_number, :govtrack_id, :first_name, :middle_name, :last_name, :congress_office, :bioguide_id, :webform_url, :youtube_url, :nickname, :phone, :fec_id, :gender, :name_suffix, :twitter_id, :sunlight_old_id, :congresspedia_url]
|
64
|
+
|
65
|
+
# Find all legislators in a particular zip code
|
66
|
+
def self.find_all_by_zip(zip)
|
67
|
+
raise ArgumentError, 'missing required parameter zip' if zip.nil?
|
68
|
+
query = {
|
69
|
+
:zip => zip,
|
70
|
+
:apikey => Daywalker.api_key
|
71
|
+
}
|
72
|
+
response = get('/legislators.allForZip.xml', :query => query)
|
73
|
+
|
74
|
+
handle_response(response)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Find one or many legislators, based on a set of conditions. See
|
78
|
+
# VALID_ATTRIBUTES for possible attributes you can search for.
|
79
|
+
#
|
80
|
+
# If you want one legislators, and you expect there is exactly one legislator, use :one. An error will be raised if there are more than one result.
|
81
|
+
#
|
82
|
+
# Daywalker::Legislator.find(:one, :state => 'NY', :district => 4)
|
83
|
+
#
|
84
|
+
# Otherwise, use :all.
|
85
|
+
#
|
86
|
+
# Daywalker::Legislator.find(:all, :state => 'NY', :title => :senator)
|
87
|
+
#
|
88
|
+
# Additionally, dynamic finders based on these attributes are available:
|
89
|
+
#
|
90
|
+
# Daywalker::Legislator.find_by_state_and_district('NY', 4)
|
91
|
+
# Daywalker::Legislator.find_all_by_state_and_senator('NY', :senator)
|
92
|
+
def self.find(sym, conditions)
|
93
|
+
url = case sym
|
94
|
+
when :one then '/legislators.get'
|
95
|
+
when :all then '/legislators.getList'
|
96
|
+
else raise ArgumentError, "invalid argument #{sym.inspect}, only :one and :all are allowed"
|
97
|
+
end
|
98
|
+
|
99
|
+
conditions = TypeConverter.normalize_conditions(conditions)
|
100
|
+
query = conditions.merge(:apikey => Daywalker.api_key)
|
101
|
+
response = get(url, :query => query)
|
102
|
+
|
103
|
+
case sym
|
104
|
+
when :one then handle_response(response).first
|
105
|
+
when :all then handle_response(response)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.method_missing(method_id, *args, &block) # :nodoc:
|
110
|
+
match = DynamicFinderMatch.new(method_id)
|
111
|
+
if match.match?
|
112
|
+
create_finder_method(method_id, match.finder, match.attribute_names)
|
113
|
+
send(method_id, *args, &block)
|
114
|
+
else
|
115
|
+
super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def self.respond_to?(method_id) # :nodoc:
|
121
|
+
match = DynamicFinderMatch.new(method_id)
|
122
|
+
if match.match?
|
123
|
+
true
|
124
|
+
else
|
125
|
+
super
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
|
132
|
+
def self.create_finder_method(method, finder, attribute_names) # :nodoc:
|
133
|
+
class_eval %{
|
134
|
+
def self.#{method}(*args) # def self.find_all_by_district_number_and_state(*args)
|
135
|
+
conditions = args.last.kind_of?(Hash) ? args.pop : {} # conditions = args.last.kind_of?(Hash) ? args.pop : {}
|
136
|
+
[:#{attribute_names.join(', :')}].each_with_index do |key, index| # [:district_number, :state].each_with_index do |key, index|
|
137
|
+
conditions[key] = args[index] # conditions[key] = args[index]
|
138
|
+
end # end
|
139
|
+
find(#{finder.inspect}, conditions) # find(:all, conditions)
|
140
|
+
end # end
|
141
|
+
}
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Daywalker
|
2
|
+
class TypeConverter # :nodoc:
|
3
|
+
def self.gender_letter_to_sym(letter)
|
4
|
+
case letter
|
5
|
+
when 'M' then :male
|
6
|
+
when 'F' then :female
|
7
|
+
else raise ArgumentError, "unknown gender #{letter.inspect}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.party_letter_to_sym(letter)
|
12
|
+
case letter
|
13
|
+
when 'D' then :democrat
|
14
|
+
when 'R' then :republican
|
15
|
+
when 'I' then :independent
|
16
|
+
else raise ArgumentError, "unknown party #{letter.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.title_abbr_to_sym(abbr)
|
21
|
+
case abbr
|
22
|
+
when 'Sen' then :senator
|
23
|
+
when 'Rep' then :representative
|
24
|
+
else raise ArgumentError, "Unknown title #{abbr.inspect}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.sym_to_title_abbr(sym)
|
29
|
+
case sym
|
30
|
+
when :senator then 'Sen'
|
31
|
+
when :representative then 'Rep'
|
32
|
+
else raise ArgumentError, "Unknown title #{sym.inspect}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.sym_to_party_letter(sym)
|
37
|
+
case sym
|
38
|
+
when :democrat then 'D'
|
39
|
+
when :republican then 'R'
|
40
|
+
when :independent then 'I'
|
41
|
+
else raise ArgumentError, "Unknown party #{sym.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.sym_to_gender_letter(sym)
|
46
|
+
case sym
|
47
|
+
when :male then 'M'
|
48
|
+
when :female then 'F'
|
49
|
+
else raise ArgumentError, "Unknown gender #{sym.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.blank_to_nil(str)
|
54
|
+
str == '' ? nil : str
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.normalize_conditions(conditions)
|
58
|
+
if conditions[:title].kind_of? Symbol
|
59
|
+
conditions[:title] = sym_to_title_abbr(conditions[:title])
|
60
|
+
end
|
61
|
+
|
62
|
+
move_value_in_hash(conditions, :district_number, :district)
|
63
|
+
move_value_in_hash(conditions, :official_rss_url, :official_rss)
|
64
|
+
|
65
|
+
if conditions[:party].kind_of? Symbol
|
66
|
+
conditions[:party] = sym_to_party_letter(conditions[:party])
|
67
|
+
end
|
68
|
+
|
69
|
+
move_value_in_hash(conditions, :website_url, :website)
|
70
|
+
move_value_in_hash(conditions, :fax_number, :fax)
|
71
|
+
move_value_in_hash(conditions, :first_name, :firstname)
|
72
|
+
move_value_in_hash(conditions, :middle_name, :middlename)
|
73
|
+
move_value_in_hash(conditions, :last_name, :lastname)
|
74
|
+
move_value_in_hash(conditions, :webform_url, :webform)
|
75
|
+
|
76
|
+
if conditions[:gender].kind_of? Symbol
|
77
|
+
conditions[:gender] = sym_to_gender_letter(conditions[:gender])
|
78
|
+
end
|
79
|
+
|
80
|
+
conditions
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
def self.move_value_in_hash(hash, from, to)
|
86
|
+
if hash.has_key? from
|
87
|
+
hash[to] = hash.delete(from)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Daywalker::District do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
FakeWeb.clean_registry
|
7
|
+
end
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
Daywalker.api_key = 'redacted'
|
11
|
+
end
|
12
|
+
|
13
|
+
after :all do
|
14
|
+
Daywalker.api_key = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'find_by_latlng' do
|
18
|
+
describe 'happy path' do
|
19
|
+
before do
|
20
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictFromLatLong.xml?apikey=urkeyhere&latitude=40.739157&longitude=-73.990929" > districts_by_latlng.xml
|
21
|
+
register_uri_with_response 'districts.getDistrictFromLatLong.xml?apikey=redacted&latitude=40.739157&longitude=-73.990929', 'districts_by_latlng.xml'
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
subject { Daywalker::District.find_by_latlng(40.739157, -73.990929) }
|
26
|
+
|
27
|
+
specify { subject.size == 1 }
|
28
|
+
specify { subject.first.state.should == 'NY' }
|
29
|
+
specify { subject.first.number.should == 14 }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'bad api key' do
|
33
|
+
before do
|
34
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictFromLatLong.xml?apikey=badkeyhere&latitude=40.739157&longitude=-73.990929" > 'districts_by_latlng_bad_api.xml'
|
35
|
+
register_uri_with_response('districts.getDistrictFromLatLong.xml?apikey=redacted&latitude=40.739157&longitude=-73.990929', 'districts_by_latlng_bad_api.xml')
|
36
|
+
end
|
37
|
+
|
38
|
+
specify 'should raise Daywalker::InvalidApiKey' do
|
39
|
+
lambda {
|
40
|
+
Daywalker::District.find_by_latlng(40.739157, -73.990929)
|
41
|
+
}.should raise_error(Daywalker::BadApiKey)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'missing latitude' do
|
46
|
+
setup do
|
47
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictFromLatLong.xml?apikey=urkeyhere&longitude=-73.990929" > 'districts_by_latlng_missing_lat.xml'
|
48
|
+
register_uri_with_response('districts.getDistrictFromLatLong.xml?apikey=redacted&longitude=-73.990929', 'districts_by_latlng_missing_lat.xml')
|
49
|
+
end
|
50
|
+
|
51
|
+
specify 'should raise ArgumentError for latitude' do
|
52
|
+
lambda {
|
53
|
+
Daywalker::District.find_by_latlng(nil, -73.990929)
|
54
|
+
}.should raise_error(ArgumentError, /latitude/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'find_by_zipcode' do
|
60
|
+
describe 'happy path' do
|
61
|
+
setup do
|
62
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictsFromZip.xml?apikey=urkeyhere&zip=27511" > districts_by_zip.xml
|
63
|
+
register_uri_with_response('districts.getDistrictsFromZip.xml?apikey=redacted&zip=27511', 'districts_by_zip.xml')
|
64
|
+
end
|
65
|
+
|
66
|
+
subject { Daywalker::District.find_by_zip(27511) }
|
67
|
+
|
68
|
+
specify { subject.size.should == 2 }
|
69
|
+
|
70
|
+
specify { subject[0].state.should == 'NC' }
|
71
|
+
specify { subject[0].number.should == 13 }
|
72
|
+
|
73
|
+
specify { subject[1].state.should == 'NC' }
|
74
|
+
specify { subject[1].number.should == 4 }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'bad api key' do
|
78
|
+
setup do
|
79
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictsFromZip.xml?apikey=badkeyhere&zip=27511" > districts_by_zip_bad_api.xml
|
80
|
+
register_uri_with_response 'districts.getDistrictsFromZip.xml?apikey=redacted&zip=27511', 'districts_by_zip_bad_api.xml'
|
81
|
+
end
|
82
|
+
|
83
|
+
specify 'should raise BadApiKey' do
|
84
|
+
lambda {
|
85
|
+
Daywalker::District.find_by_zip(27511)
|
86
|
+
}.should raise_error(Daywalker::BadApiKey)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'missing zip' do
|
91
|
+
setup do
|
92
|
+
# curl -i "http://services.sunlightlabs.com/api/districts.getDistrictsFromZip.xml?apikey=urkeyhere" > districts_by_zip_missing_zip.xml
|
93
|
+
register_uri_with_response 'districts.getDistrictsFromZip.xml?apikey=redacted', 'districts_by_zip_missing_zip.xml'
|
94
|
+
end
|
95
|
+
|
96
|
+
specify 'should raise ArgumentError for missing zip' do
|
97
|
+
lambda {
|
98
|
+
Daywalker::District.find_by_zip(nil)
|
99
|
+
}.should raise_error(ArgumentError, /zip/)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Daywalker::DynamicFinderMatch do
|
4
|
+
describe 'finding all by valid attributes (state and district number)' do
|
5
|
+
subject { Daywalker::DynamicFinderMatch.new(:find_all_by_state_and_district_number) }
|
6
|
+
|
7
|
+
specify 'should have :all finder' do
|
8
|
+
subject.finder.should == :all
|
9
|
+
end
|
10
|
+
|
11
|
+
specify 'should have attributes named [:state, :district_number]' do
|
12
|
+
subject.attribute_names.should == [:state, :district_number]
|
13
|
+
end
|
14
|
+
|
15
|
+
specify { should be_a_match }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'finding all by invalid attributes (foo and bar)' do
|
19
|
+
subject { Daywalker::DynamicFinderMatch.new(:find_all_by_foo_and_bar) }
|
20
|
+
specify { should_not be_a_match }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'finding one by valid attrribute (govtrack_id)' do
|
24
|
+
subject { Daywalker::DynamicFinderMatch.new(:find_by_govtrack_id) }
|
25
|
+
specify { should be_a_match }
|
26
|
+
specify 'should have :govtrack_id attribute' do
|
27
|
+
subject.attribute_names.should == [:govtrack_id]
|
28
|
+
end
|
29
|
+
specify 'should have :one finder' do
|
30
|
+
subject.finder.should == :one
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Daywalker::Legislator do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
FakeWeb.clean_registry
|
7
|
+
end
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
Daywalker.api_key = 'redacted'
|
11
|
+
end
|
12
|
+
|
13
|
+
after :all do
|
14
|
+
Daywalker.api_key = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'find_all_by_zip' do
|
18
|
+
|
19
|
+
describe 'happy path' do
|
20
|
+
setup do
|
21
|
+
# curl -i "http://services.sunlightlabs.com/api/legislators.allForZip.xml?zip=27511&apikey=redacted" > legislators_by_zip.xml
|
22
|
+
register_uri_with_response 'legislators.allForZip.xml?zip=27511&apikey=redacted', 'legislators_by_zip.xml'
|
23
|
+
|
24
|
+
@legislators = Daywalker::Legislator.find_all_by_zip 27511
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'return legislators identified by votersmart ids 119, 21082, 21787, and 10205' do
|
28
|
+
@legislators.map{|each| each.votesmart_id}.should == [119, 21082, 21787, 10205]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'with a bad API key' do
|
33
|
+
setup do
|
34
|
+
# curl -i "http://services.sunlightlabs.com/api/legislators.allForZip.xml?zip=27511&apikey=redacted" > legislators_by_zip
|
35
|
+
register_uri_with_response 'legislators.allForZip.xml?zip=27511&apikey=redacted', 'legislators_by_zip_bad_api.xml'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should raise bad API key error' do
|
39
|
+
lambda {
|
40
|
+
Daywalker::Legislator.find_all_by_zip 27511
|
41
|
+
}.should raise_error(Daywalker::BadApiKey)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'without a zip code' do
|
46
|
+
it 'should raise ArgumentError for missing zip' do
|
47
|
+
lambda {
|
48
|
+
Daywalker::Legislator.find_all_by_zip nil
|
49
|
+
}.should raise_error(ArgumentError, /zip/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'found with find(:one)' do
|
55
|
+
describe 'by state and district, with one result,' do
|
56
|
+
describe 'happy path' do
|
57
|
+
before do
|
58
|
+
register_uri_with_response 'legislators.get?apikey=redacted&state=NY&district=4', 'legislators_find_by_ny_district_4.xml'
|
59
|
+
@legislator = Daywalker::Legislator.find(:one, :state => 'NY', :district => 4)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
it 'should have votesmart id 119' do
|
64
|
+
@legislator.votesmart_id.should == 119
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'by state and district, with bad API key' do
|
69
|
+
before do
|
70
|
+
register_uri_with_response 'legislators.get?apikey=redacted&state=NY&district=4', 'legislators_find_by_ny_district_4_bad_api.xml'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should raise a missing parameter error for zip' do
|
74
|
+
lambda {
|
75
|
+
Daywalker::Legislator.find(:one, :state => 'NY', :district => 4)
|
76
|
+
}.should raise_error(Daywalker::BadApiKey)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'found with find(:all)' do
|
83
|
+
describe 'by state and title, with multiple results,' do
|
84
|
+
describe 'happy path' do
|
85
|
+
before do
|
86
|
+
# curl -i "http://services.sunlightlabs.com/api/legislators.getList.xml?state=NY&title=Sen&apikey=redacted" > legislators_find_ny_senators.xml
|
87
|
+
register_uri_with_response 'legislators.getList?state=NY&apikey=redacted&title=Sen', 'legislators_find_ny_senators.xml'
|
88
|
+
@legislators = Daywalker::Legislator.find(:all, :state => 'NY', :title => :senator)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return legislators with votesmart ids 55463 and 26976' do
|
92
|
+
@legislators.map{|each| each.votesmart_id}.should == [55463, 26976]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'with bad API key' do
|
97
|
+
before do
|
98
|
+
register_uri_with_response 'legislators.getList?state=NY&apikey=redacted&title=Sen', 'legislators_find_ny_senators_bad_api.xml'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should raise BadApiKey error' do
|
102
|
+
lambda {
|
103
|
+
Daywalker::Legislator.find(:all, :state => 'NY', :title => :senator)
|
104
|
+
}.should raise_error(Daywalker::BadApiKey)
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'found with find(:zomg)' do
|
112
|
+
it 'should raise ArgumentError' do
|
113
|
+
lambda {
|
114
|
+
Daywalker::Legislator.find(:zomg, {})
|
115
|
+
}.should raise_error(ArgumentError, /zomg/)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# TODO switch this to mocking
|
120
|
+
describe 'dynamic finder find_all_by_state_and_title' do
|
121
|
+
before do
|
122
|
+
register_uri_with_response 'legislators.getList?state=NY&apikey=redacted&title=Sen', 'legislators_find_ny_senators.xml'
|
123
|
+
|
124
|
+
@legislators = Daywalker::Legislator.find_all_by_state_and_title('NY', :senator)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should return legislators with votesmart ids 55463 and 26976' do
|
128
|
+
@legislators.map{|each| each.votesmart_id}.should == [55463, 26976]
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should respond to find_all_by_state_and_title' do
|
132
|
+
Daywalker::Legislator.should respond_to(:find_all_by_state_and_title)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
describe 'parsed from XML' do
|
138
|
+
setup do
|
139
|
+
@xml = <<-XML
|
140
|
+
<legislator>
|
141
|
+
<district>4</district>
|
142
|
+
<title>Rep</title>
|
143
|
+
<eventful_id>P0-001-000016562-5</eventful_id>
|
144
|
+
<in_office>1</in_office>
|
145
|
+
<state>NC</state>
|
146
|
+
<votesmart_id>119</votesmart_id>
|
147
|
+
<official_rss></official_rss>
|
148
|
+
<party>D</party>
|
149
|
+
<email></email>
|
150
|
+
<crp_id>N00002260</crp_id>
|
151
|
+
<website>http://price.house.gov/</website>
|
152
|
+
<fax>202-225-2014</fax>
|
153
|
+
<govtrack_id>400326</govtrack_id>
|
154
|
+
<firstname>David</firstname>
|
155
|
+
<middlename>Eugene</middlename>
|
156
|
+
<lastname>Price</lastname>
|
157
|
+
<congress_office>2162 Rayburn House Office Building</congress_office>
|
158
|
+
<bioguide_id>P000523</bioguide_id>
|
159
|
+
<webform>http://price.house.gov/contact/contact_form.shtml</webform>
|
160
|
+
<youtube_url>http://www.youtube.com/repdavidprice</youtube_url>
|
161
|
+
<nickname></nickname>
|
162
|
+
<phone>202-225-1784</phone>
|
163
|
+
<fec_id>H6NC04037</fec_id>
|
164
|
+
<gender>M</gender>
|
165
|
+
<name_suffix></name_suffix>
|
166
|
+
<twitter_id></twitter_id>
|
167
|
+
<sunlight_old_id>fakeopenID319</sunlight_old_id>
|
168
|
+
<congresspedia_url>http://www.sourcewatch.org/index.php?title=David_Price</congresspedia_url>
|
169
|
+
</legislator>
|
170
|
+
XML
|
171
|
+
end
|
172
|
+
subject { Daywalker::Legislator.parse(@xml) }
|
173
|
+
|
174
|
+
specify { subject.district_number.should == 4 }
|
175
|
+
specify { subject.title.should == :representative }
|
176
|
+
specify { subject.eventful_id.should == 'P0-001-000016562-5' }
|
177
|
+
specify { subject.in_office.should be_true }
|
178
|
+
specify { subject.state.should == 'NC' }
|
179
|
+
specify { subject.votesmart_id.should == 119 }
|
180
|
+
specify { subject.official_rss_url.should be_nil }
|
181
|
+
specify { subject.party.should == :democrat }
|
182
|
+
specify { subject.email.should be_nil }
|
183
|
+
specify { subject.crp_id.should == 'N00002260' }
|
184
|
+
specify { subject.website_url.should == 'http://price.house.gov/' }
|
185
|
+
specify { subject.fax_number.should == '202-225-2014' }
|
186
|
+
specify { subject.govtrack_id.should == 400326 }
|
187
|
+
specify { subject.first_name.should == 'David' }
|
188
|
+
specify { subject.middle_name.should == 'Eugene' }
|
189
|
+
specify { subject.last_name.should == 'Price' }
|
190
|
+
specify { subject.congress_office.should == '2162 Rayburn House Office Building' }
|
191
|
+
specify { subject.bioguide_id.should == 'P000523' }
|
192
|
+
specify { subject.webform_url.should == 'http://price.house.gov/contact/contact_form.shtml' }
|
193
|
+
specify { subject.youtube_url.should == 'http://www.youtube.com/repdavidprice' }
|
194
|
+
specify { subject.nickname.should be_nil }
|
195
|
+
specify { subject.phone.should == '202-225-1784' }
|
196
|
+
specify { subject.fec_id.should == 'H6NC04037' }
|
197
|
+
specify { subject.gender.should == :male }
|
198
|
+
specify { subject.name_suffix.should be_nil }
|
199
|
+
specify { subject.twitter_id.should be_nil }
|
200
|
+
specify { subject.sunlight_old_id.should == 'fakeopenID319' }
|
201
|
+
specify { subject.congresspedia_url.should == 'http://www.sourcewatch.org/index.php?title=David_Price' }
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Daywalker::TypeConverter do
|
4
|
+
describe 'gender_letter_to_sym' do
|
5
|
+
it 'should convert F to :female' do
|
6
|
+
Daywalker::TypeConverter.gender_letter_to_sym('F').should == :female
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should convert M to :male' do
|
10
|
+
Daywalker::TypeConverter.gender_letter_to_sym('M').should == :male
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should raise ArgumentError for unknown genders' do
|
14
|
+
lambda {
|
15
|
+
Daywalker::TypeConverter.gender_letter_to_sym('aiee')
|
16
|
+
}.should raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'party_letter_to_sym' do
|
21
|
+
it 'should convert D to :democrat' do
|
22
|
+
Daywalker::TypeConverter.party_letter_to_sym('D').should == :democrat
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should convert R to democrat' do
|
26
|
+
Daywalker::TypeConverter.party_letter_to_sym('R').should == :republican
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should convert I to independent' do
|
30
|
+
Daywalker::TypeConverter.party_letter_to_sym('I').should == :independent
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should raise ArgumentError for unknown parties' do
|
34
|
+
lambda {
|
35
|
+
Daywalker::TypeConverter.party_letter_to_sym('zomg')
|
36
|
+
}.should raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'title_abbr_to_sym' do
|
41
|
+
it 'should convert Sen to :senator' do
|
42
|
+
Daywalker::TypeConverter.title_abbr_to_sym('Sen').should == :senator
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should convert Rep to :representative' do
|
46
|
+
Daywalker::TypeConverter.title_abbr_to_sym('Rep').should == :representative
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should raise ArgumentError for unknown titles' do
|
50
|
+
lambda {
|
51
|
+
Daywalker::TypeConverter.title_abbr_to_sym('zomg')
|
52
|
+
}.should raise_error(ArgumentError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'sym_to_title_abbr' do
|
57
|
+
it 'should convert :senator to Sen' do
|
58
|
+
Daywalker::TypeConverter.sym_to_title_abbr(:senator).should == 'Sen'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should convert :representative to Rep' do
|
62
|
+
Daywalker::TypeConverter.sym_to_title_abbr(:representative).should == 'Rep'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should raise ArgumentError for unknown titles' do
|
66
|
+
lambda {
|
67
|
+
Daywalker::TypeConverter.sym_to_title_abbr(:zomg)
|
68
|
+
}.should raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'sym_to_party_letter' do
|
73
|
+
it 'should convert :democrat to D' do
|
74
|
+
Daywalker::TypeConverter.sym_to_party_letter(:democrat).should == 'D'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should convert :republican to R' do
|
78
|
+
Daywalker::TypeConverter.sym_to_party_letter(:republican).should == 'R'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should convert :independent to I' do
|
82
|
+
Daywalker::TypeConverter.sym_to_party_letter(:independent).should == 'I'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should raise ArgumentError for unknown parties' do
|
86
|
+
lambda {
|
87
|
+
Daywalker::TypeConverter.sym_to_party_letter(:zomg)
|
88
|
+
}.should raise_error(ArgumentError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'sym_to_gender_letter' do
|
93
|
+
it 'should convert :male to M' do
|
94
|
+
Daywalker::TypeConverter.sym_to_gender_letter(:male).should == 'M'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should convert :female to F' do
|
98
|
+
Daywalker::TypeConverter.sym_to_gender_letter(:female).should == 'F'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should raise ArgumentError for unknown genders' do
|
102
|
+
lambda {
|
103
|
+
Daywalker::TypeConverter.sym_to_gender_letter(:zomg)
|
104
|
+
}.should raise_error(ArgumentError)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'blank_to_nil' do
|
109
|
+
it 'should convert "" to nil' do
|
110
|
+
Daywalker::TypeConverter.blank_to_nil('').should be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should leave "zomg" alone' do
|
114
|
+
Daywalker::TypeConverter.blank_to_nil('zomg').should == 'zomg'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'normalize_conditions' do
|
119
|
+
before do
|
120
|
+
@conditions = {
|
121
|
+
:title => :senator,
|
122
|
+
:district_number => 5,
|
123
|
+
:official_rss_url => 'http://zomg.com/index.rss',
|
124
|
+
:party => :democrat,
|
125
|
+
:website_url => 'http://zomg.com',
|
126
|
+
:fax_number => '1800vote4me',
|
127
|
+
:first_name => 'John',
|
128
|
+
:middle_name => 'Q',
|
129
|
+
:last_name => 'Doe',
|
130
|
+
:webform_url => 'http://zomg.com/contact',
|
131
|
+
:gender => :male
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should convert title value' do
|
136
|
+
Daywalker::TypeConverter.should_receive(:sym_to_title_abbr).with(:senator)
|
137
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should copy district_number value to district' do
|
141
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:district].should == 5
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should remove district_number value' do
|
145
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:district_number)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should copy official_rss_url value to official_rss' do
|
149
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:official_rss].should == 'http://zomg.com/index.rss'
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should remove official_rss_url value' do
|
153
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:official_rss_url)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should convert party value' do
|
157
|
+
Daywalker::TypeConverter.should_receive(:sym_to_party_letter).with(:democrat)
|
158
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should copy website_url value to website' do
|
162
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:website].should == 'http://zomg.com'
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should remove website_url value' do
|
166
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:website_url)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should copy fax_number value to fax' do
|
170
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:fax].should == '1800vote4me'
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should remove fax_number value' do
|
174
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:fax_number)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should copy first_name value to firstname' do
|
178
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:firstname].should == 'John'
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should remove first_name value' do
|
182
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:first_name)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should copy middle_name value to middlename' do
|
186
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:middlename].should == 'Q'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should remove middle_name value' do
|
190
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:middle_name)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should copy last_name value to lastname' do
|
194
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:lastname].should == 'Doe'
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should remove last_name value' do
|
198
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:last_name)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should copy webform_url value to webform' do
|
202
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)[:webform].should == 'http://zomg.com/contact'
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should remove webform_url value' do
|
206
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions).should_not have_key(:webform_url)
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should convert gender value' do
|
210
|
+
Daywalker::TypeConverter.should_receive(:sym_to_gender_letter).with(:male)
|
211
|
+
Daywalker::TypeConverter.normalize_conditions(@conditions)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Wed, 04 Feb 2009 03:35:16 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: application/xml
|
5
|
+
Transfer-Encoding: chunked
|
6
|
+
|
7
|
+
<response><districts><district><state>NY</state><number>14</number></district></districts></response>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
HTTP/1.1 400 Bad Request
|
2
|
+
Date: Wed, 04 Feb 2009 03:40:12 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: text/html; charset=utf-8
|
5
|
+
Vary: Accept-Encoding
|
6
|
+
Connection: close
|
7
|
+
Transfer-Encoding: chunked
|
8
|
+
|
9
|
+
Missing Parameter: 'latitude'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Wed, 04 Feb 2009 03:42:26 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: application/xml
|
5
|
+
Transfer-Encoding: chunked
|
6
|
+
|
7
|
+
<response><districts><district><state>NC</state><number>13</number></district> <district><state>NC</state><number>4</number></district></districts></response>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
HTTP/1.1 400 Bad Request
|
2
|
+
Date: Wed, 04 Feb 2009 03:45:33 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: text/html; charset=utf-8
|
5
|
+
Vary: Accept-Encoding
|
6
|
+
Connection: close
|
7
|
+
Transfer-Encoding: chunked
|
8
|
+
|
9
|
+
Missing Parameter: 'zip'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Wed, 04 Feb 2009 04:50:33 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: application/xml
|
5
|
+
Transfer-Encoding: chunked
|
6
|
+
|
7
|
+
<response><legislators><legislator><district>4</district><title>Rep</title><eventful_id>P0-001-000016562-5</eventful_id><in_office>1</in_office><state>NC</state><votesmart_id>119</votesmart_id><official_rss></official_rss><party>D</party><email></email><crp_id>N00002260</crp_id><website>http://price.house.gov/</website><fax>202-225-2014</fax><govtrack_id>400326</govtrack_id><firstname>David</firstname><middlename>Eugene</middlename><lastname>Price</lastname><congress_office>2162 Rayburn House Office Building</congress_office><bioguide_id>P000523</bioguide_id><webform>http://price.house.gov/contact/contact_form.shtml</webform><youtube_url>http://www.youtube.com/repdavidprice</youtube_url><nickname></nickname><phone>202-225-1784</phone><fec_id>H6NC04037</fec_id><gender>M</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id>fakeopenID319</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=David_Price</congresspedia_url></legislator> <legislator><district>Junior Seat</district><title>Sen</title><eventful_id></eventful_id><in_office>1</in_office><state>NC</state><votesmart_id>21082</votesmart_id><official_rss></official_rss><party>D</party><email></email><crp_id></crp_id><website></website><fax></fax><govtrack_id></govtrack_id><firstname>Kay</firstname><middlename>R.</middlename><lastname>Hagan</lastname><congress_office></congress_office><bioguide_id>H001049</bioguide_id><webform></webform><youtube_url></youtube_url><nickname></nickname><phone></phone><fec_id></fec_id><gender>F</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id></sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=Kay_R._Hagan</congresspedia_url></legislator> <legislator><district>Senior Seat</district><title>Sen</title><eventful_id>P0-001-000016040-8</eventful_id><in_office>1</in_office><state>NC</state><votesmart_id>21787</votesmart_id><official_rss>http://burr.senate.gov/index.cfm?FuseAction=RSS.Feed</official_rss><party>R</party><email></email><crp_id>N00002221</crp_id><website>http://burr.senate.gov/</website><fax>202-228-2981</fax><govtrack_id>400054</govtrack_id><firstname>Richard</firstname><middlename>M.</middlename><lastname>Burr</lastname><congress_office>217 Russell Senate Office Building</congress_office><bioguide_id>B001135</bioguide_id><webform>http://burr.senate.gov/public/index.cfm?FuseAction=Contact.Home</webform><youtube_url>http://www.youtube.com/senatorrichardburr</youtube_url><nickname></nickname><phone>202-224-3154</phone><fec_id>S4NC00089</fec_id><gender>M</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id>fakeopenID449</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=Richard_Burr</congresspedia_url></legislator> <legislator><district>13</district><title>Rep</title><eventful_id>P0-001-000016512-0</eventful_id><in_office>1</in_office><state>NC</state><votesmart_id>10205</votesmart_id><official_rss></official_rss><party>D</party><email></email><crp_id>N00025093</crp_id><website>http://www.house.gov/bradmiller/</website><fax>202-225-0181</fax><govtrack_id>400280</govtrack_id><firstname>Ralph</firstname><middlename>Bradley</middlename><lastname>Miller</lastname><congress_office>1722 Longworth House Office Building</congress_office><bioguide_id>M001154</bioguide_id><webform>http://bradmiller.house.gov/?sectionid=17&sectiontree=9,17</webform><youtube_url>http://www.youtube.com/MillerNC13</youtube_url><nickname>Brad</nickname><phone>202-225-3032</phone><fec_id>H2NC13029</fec_id><gender>M</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id>fakeopenID275</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=Brad_Miller</congresspedia_url></legislator></legislators></response>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Fri, 06 Feb 2009 07:27:16 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: application/xml
|
5
|
+
Transfer-Encoding: chunked
|
6
|
+
|
7
|
+
<response><legislator><district>4</district><title>Rep</title><eventful_id>P0-001-000016562-5</eventful_id><in_office>1</in_office><state>NC</state><votesmart_id>119</votesmart_id><official_rss></official_rss><party>D</party><email></email><crp_id>N00002260</crp_id><website>http://price.house.gov/</website><fax>202-225-2014</fax><govtrack_id>400326</govtrack_id><firstname>David</firstname><middlename>Eugene</middlename><lastname>Price</lastname><congress_office>2162 Rayburn House Office Building</congress_office><bioguide_id>P000523</bioguide_id><webform>http://price.house.gov/contact/contact_form.shtml</webform><youtube_url>http://www.youtube.com/repdavidprice</youtube_url><nickname></nickname><phone>202-225-1784</phone><fec_id>H6NC04037</fec_id><gender>M</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id>fakeopenID319</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=David_Price</congresspedia_url></legislator></response>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Fri, 06 Feb 2009 07:20:56 GMT
|
3
|
+
Server: Apache/2.2.3 (Debian) mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch11
|
4
|
+
Content-Type: application/xml
|
5
|
+
Transfer-Encoding: chunked
|
6
|
+
|
7
|
+
<response><legislators><legislator><district>Junior Seat</district><title>Sen</title><eventful_id>P0-001-000015656-6</eventful_id><in_office>1</in_office><state>NY</state><votesmart_id>55463</votesmart_id><official_rss>http://clinton.senate.gov/</official_rss><party>D</party><email></email><crp_id>N00000019</crp_id><website>http://clinton.senate.gov/</website><fax>202-228-0282</fax><govtrack_id>300022</govtrack_id><firstname>Hillary</firstname><middlename>Rodham</middlename><lastname>Clinton</lastname><congress_office>476 Russell Senate Office Building</congress_office><bioguide_id>C001041</bioguide_id><webform>http://clinton.senate.gov/contact/webform.cfm</webform><youtube_url></youtube_url><nickname></nickname><phone>202-224-4451</phone><fec_id>S0NY00188</fec_id><gender>F</gender><name_suffix></name_suffix><twitter_id>hillaryclinton</twitter_id><sunlight_old_id>fakeopenID456</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=Hillary_Clinton</congresspedia_url></legislator> <legislator><district>Senior Seat</district><title>Sen</title><eventful_id>P0-001-000016112-4</eventful_id><in_office>1</in_office><state>NY</state><votesmart_id>26976</votesmart_id><official_rss></official_rss><party>D</party><email></email><crp_id>N00001093</crp_id><website>http://schumer.senate.gov</website><fax>202-228-3027</fax><govtrack_id>300087</govtrack_id><firstname>Charles</firstname><middlename>E.</middlename><lastname>Schumer</lastname><congress_office>313 Hart Senate Office Building</congress_office><bioguide_id>S000148</bioguide_id><webform>http://schumer.senate.gov/SchumerWebsite/contact/webform.cfm</webform><youtube_url>http://www.youtube.com/senatorschumer</youtube_url><nickname>Chuck</nickname><phone>202-224-6542</phone><fec_id>S8NY00082</fec_id><gender>M</gender><name_suffix></name_suffix><twitter_id></twitter_id><sunlight_old_id>fakeopenID518</sunlight_old_id><congresspedia_url>http://www.sourcewatch.org/index.php?title=Chuck_Schumer</congresspedia_url></legislator></legislators></response>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'fake_web'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__), '..', 'lib')
|
7
|
+
|
8
|
+
require 'daywalker'
|
9
|
+
|
10
|
+
FakeWeb.allow_net_connect = false
|
11
|
+
|
12
|
+
Spec::Runner.configure do |config|
|
13
|
+
end
|
14
|
+
|
15
|
+
def fixture_path_for(response)
|
16
|
+
File.join File.dirname(__FILE__), 'fixtures', response
|
17
|
+
end
|
18
|
+
|
19
|
+
def register_uri_with_response(uri, response)
|
20
|
+
FakeWeb.register_uri("http://services.sunlightlabs.com/api/#{uri}", :response => fixture_path_for(response))
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: technicalpickles-daywalker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Josh Nichols
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-10 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: TODO
|
17
|
+
email: josh@technicalpickles.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.rdoc
|
26
|
+
- VERSION.yml
|
27
|
+
- lib/daywalker
|
28
|
+
- lib/daywalker/base.rb
|
29
|
+
- lib/daywalker/district.rb
|
30
|
+
- lib/daywalker/dynamic_finder_match.rb
|
31
|
+
- lib/daywalker/legislator.rb
|
32
|
+
- lib/daywalker/type_converter.rb
|
33
|
+
- lib/daywalker.rb
|
34
|
+
- spec/daywalker
|
35
|
+
- spec/daywalker/district_spec.rb
|
36
|
+
- spec/daywalker/dynamic_finder_match_spec.rb
|
37
|
+
- spec/daywalker/legislator_spec.rb
|
38
|
+
- spec/daywalker/type_converter_spec.rb
|
39
|
+
- spec/daywalker_spec.rb
|
40
|
+
- spec/fixtures
|
41
|
+
- spec/fixtures/districts_by_latlng.xml
|
42
|
+
- spec/fixtures/districts_by_latlng_bad_api.xml
|
43
|
+
- spec/fixtures/districts_by_latlng_missing_lat.xml
|
44
|
+
- spec/fixtures/districts_by_zip.xml
|
45
|
+
- spec/fixtures/districts_by_zip_bad_api.xml
|
46
|
+
- spec/fixtures/districts_by_zip_missing_zip.xml
|
47
|
+
- spec/fixtures/legislators_by_zip.xml
|
48
|
+
- spec/fixtures/legislators_by_zip_bad_api.xml
|
49
|
+
- spec/fixtures/legislators_find_by_ny_district_4.xml
|
50
|
+
- spec/fixtures/legislators_find_by_ny_district_4_bad_api.xml
|
51
|
+
- spec/fixtures/legislators_find_ny_senators.xml
|
52
|
+
- spec/fixtures/legislators_find_ny_senators_bad_api.xml
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://github.com/technicalpickles/daywalker
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --inline-source
|
59
|
+
- --charset=UTF-8
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.2.0
|
78
|
+
signing_key:
|
79
|
+
specification_version: 2
|
80
|
+
summary: TODO
|
81
|
+
test_files: []
|
82
|
+
|