votesmart 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/History.txt +20 -0
- data/README.rdoc +48 -0
- data/Rakefile +45 -0
- data/VERSION.yml +4 -0
- data/lib/mcll4r/MIT-LICENSE +20 -0
- data/lib/mcll4r/README +19 -0
- data/lib/mcll4r/mcll4r.rb +24 -0
- data/lib/mcll4r/mcll4r_test.rb +35 -0
- data/lib/vote_smart.rb +22 -0
- data/lib/vote_smart/address.rb +42 -0
- data/lib/vote_smart/candidate.rb +32 -0
- data/lib/vote_smart/candidate_bio.rb +16 -0
- data/lib/vote_smart/candidate_office.rb +15 -0
- data/lib/vote_smart/committee.rb +23 -0
- data/lib/vote_smart/common.rb +97 -0
- data/lib/vote_smart/district.rb +38 -0
- data/lib/vote_smart/election.rb +21 -0
- data/lib/vote_smart/leadership.rb +16 -0
- data/lib/vote_smart/local.rb +21 -0
- data/lib/vote_smart/measure.rb +16 -0
- data/lib/vote_smart/notes.rb +11 -0
- data/lib/vote_smart/npat.rb +11 -0
- data/lib/vote_smart/office.rb +119 -0
- data/lib/vote_smart/official.rb +131 -0
- data/lib/vote_smart/phone.rb +12 -0
- data/lib/vote_smart/rating.rb +43 -0
- data/lib/vote_smart/state.rb +29 -0
- data/lib/vote_smart/vote.rb +70 -0
- data/lib/votesmart.rb +1 -0
- data/script/autospec +6 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/is_gem_built +40 -0
- data/spec/responses/Address.get_office.106446.js +1 -0
- data/spec/responses/Address.get_office.1721.js +1 -0
- data/spec/responses/District.get_by_office_state.7.GA.js +1 -0
- data/spec/responses/District.get_by_office_state.8.GA.js +1 -0
- data/spec/responses/District.get_by_office_state.9.GA.js +1 -0
- data/spec/responses/Office.get_offices_by_type.C.js +1 -0
- data/spec/responses/Office.get_offices_by_type.L.js +1 -0
- data/spec/responses/Office.get_offices_by_type.P.js +1 -0
- data/spec/responses/Office.get_offices_by_type.S.js +1 -0
- data/spec/responses/Office.get_types.js +1 -0
- data/spec/responses/Official.get_by_district.20451.js +1 -0
- data/spec/responses/Official.get_by_district.20689.js +1 -0
- data/spec/responses/Official.get_by_district.21397.js +1 -0
- data/spec/responses/Official.get_by_district.21946.js +1 -0
- data/spec/responses/Official.get_by_office_state.12.CO.js +1 -0
- data/spec/responses/Official.get_by_office_state.12.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.13.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.33.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.42.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.44.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.45.GA.js +1 -0
- data/spec/responses/Official.get_by_office_state.53.GA.js +1 -0
- data/spec/responses/Rating.get_sig.1863.js +1 -0
- data/spec/responses/State.get_state.GA.js +1 -0
- data/spec/responses/State.get_state_ids.js +1 -0
- data/spec/responses/authorization_failed.js +1 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/vote_smart/district_spec.rb +36 -0
- data/spec/vote_smart/office_spec.rb +96 -0
- data/spec/vote_smart/official_spec.rb +56 -0
- data/spec/vote_smart/rating_spec.rb +15 -0
- data/spec/vote_smart/state_spec.rb +28 -0
- data/tasks/spec_json.rake +64 -0
- data/votesmart.gemspec +116 -0
- metadata +149 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class District < Common
|
4
|
+
|
5
|
+
attr_accessor :id, :name, :office_id, :state_id
|
6
|
+
|
7
|
+
attr_accessor :office
|
8
|
+
|
9
|
+
set_attribute_map "districtId" => :id, "name" => :name, "officeId" => :office_id, "stateId" => :state_id
|
10
|
+
|
11
|
+
def number
|
12
|
+
return unless name
|
13
|
+
|
14
|
+
scan = name.scan(/District (\d[0-9]*)/) || []
|
15
|
+
scan = scan.first || []
|
16
|
+
num = scan.first
|
17
|
+
num ? num.to_i : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def official
|
21
|
+
@official ||= Official.find_by_district(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find_all_by_office_and_state office, state
|
25
|
+
find_all_by_office_id_and_state_id(office.id, state.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.find_all_by_office_id_and_state_id office_id, state_id
|
29
|
+
response_child(get_by_office_state(office_id, state_id), "districtList", "district").collect {|attributes| District.new(attributes)}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns districts service the office and state provided
|
33
|
+
def self.get_by_office_state office_id, state_id = 'NA', district_name = ''
|
34
|
+
request("District.getByOfficeState", "officeId" => office_id, "stateId" => state_id, "districtName" => district_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Election < Common
|
4
|
+
|
5
|
+
# Returns detailed election information
|
6
|
+
def self.get_election election_id
|
7
|
+
request("Election.getElection", "electionId" => election_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# returns a list of elections based on the criteria
|
11
|
+
def self.get_election_by_year_state year, state_id
|
12
|
+
request("Election.getElectionByYearState", "year" => year, "stateId" => state_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a list of candidates in the election and election stage provided
|
16
|
+
def self.get_stage_candidates election_id, stage_id, party = ""
|
17
|
+
request("Election.getStageCandidates", "electionId" => election_id, "stageId" => stage_id, "party" => party)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Leadership < Common
|
4
|
+
|
5
|
+
# Returns a list of leadership positions
|
6
|
+
def self.get_positions state_id = "NA", office_id = nil
|
7
|
+
request("Leadership.getPositions", "stateId" => state_id, "officeId" => office_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns a list of candidates in specific leadership positions
|
11
|
+
def self.get_officials leadership_id, state_id = "NA"
|
12
|
+
request("Leadership.getOfficials", "leadershipId" => leadership_id, "stateId" => state_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Local < Common
|
4
|
+
|
5
|
+
# Returns a list of cities in a given state
|
6
|
+
def get_cities state_id
|
7
|
+
request("Local.getCities", "stateId" => state_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns a list of counties in a given state.
|
11
|
+
def get_counties state_id
|
12
|
+
request("Local.getCounties", "stateId" => state_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
def get_officials local_id
|
17
|
+
request("Local.getOfficials", "localId" => local_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Measure < Common
|
4
|
+
|
5
|
+
# Returns a ballot measure's details
|
6
|
+
def self.get_measure measure_id
|
7
|
+
request("Measure.getMeasure", "measureId" => measure_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns a list of ballot measures that fit the criteria
|
11
|
+
def self.get_measures_by_year_state year, state_id
|
12
|
+
request("Measure.getMeasuresByYearState", "year" => year, "stateId" => state_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Office < Common
|
4
|
+
|
5
|
+
attr_accessor :id, :type_id, :level_id, :branch_id, :name, :title, :short_title
|
6
|
+
|
7
|
+
attr_accessor :office
|
8
|
+
|
9
|
+
set_attribute_map "officeId" => :id, "officeTypeId" => :type_id, "officeLevelId" => :level_id,
|
10
|
+
"officeBranchId" => :branch_id, "name" => :name, "title" => :title, "shortTitle" => :short_title
|
11
|
+
|
12
|
+
def districts_by_state_id state_id
|
13
|
+
@districts_by_state ||= {}
|
14
|
+
districts = District.find_all_by_office_id_and_state_id(self.id, state_id)
|
15
|
+
districts.each { |district| district.office = self }
|
16
|
+
@districts_by_state[state_id] ||= districts
|
17
|
+
end
|
18
|
+
|
19
|
+
def district_by_state_id_and_number state_id, number
|
20
|
+
number = number.to_i
|
21
|
+
districts = districts_by_state_id(state_id)
|
22
|
+
districts.find {|district| district.number == number}
|
23
|
+
end
|
24
|
+
|
25
|
+
def official_by_state_id state_id
|
26
|
+
@official_by_state ||= {}
|
27
|
+
official = Official.find_by_office_id_and_state_id(self.id, state_id)
|
28
|
+
official.office = self if official
|
29
|
+
@official_by_state[state_id] ||= official
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.all
|
33
|
+
Type.all.collect { |type| find_all_by_type(type) }.uniq.flatten
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_all_by_type type
|
37
|
+
find_all_by_type_id(type.id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_all_by_type_id type_id
|
41
|
+
response_child(get_offices_by_type(type_id), "offices", "office").collect {|attributes| Office.new(attributes)}
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.find_by_name name
|
45
|
+
Office.all.collect {|office| office if office.name == name }.compact.first
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.find_all_by_name names
|
49
|
+
offices = Office.all
|
50
|
+
names.collect {|name| offices.find {|office| office.name == name }}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Gets a list of office types
|
54
|
+
def self.get_types
|
55
|
+
request("Office.getTypes")
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns branches of government and their respective IDs
|
59
|
+
def self.get_branches
|
60
|
+
request("Office.getBranches")
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns levels of government and their respective IDs
|
64
|
+
def self.get_levels
|
65
|
+
request("Office.getLevels")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a list of offices by office type
|
69
|
+
def self.get_offices_by_type type_id
|
70
|
+
request("Office.getOfficesByType", "typeId" => type_id)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns a list of offices by level of government
|
74
|
+
def self.get_offices_by_level level_id
|
75
|
+
request("Office.getOfficesByLevel", "levelId" => level_id)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a list of offices by office type and level of government
|
79
|
+
def self.get_offices_by_type_level type_id, level_id
|
80
|
+
request("Office.getOfficesByType", "levelId" => level_id, "typeId" => type_id)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns a list of offices by branch and level of government
|
84
|
+
def self.get_offices_by_branch_level branch_id, level_id
|
85
|
+
request("Office.getOfficesByBranchLevel", "branchId" => branch_id, "levelId" => level_id)
|
86
|
+
end
|
87
|
+
|
88
|
+
class Type < Common
|
89
|
+
|
90
|
+
|
91
|
+
attr_accessor :id, :level_id, :branch_id, :name
|
92
|
+
|
93
|
+
set_attribute_map "officeTypeId" => :id, "officeLevelId" => :level_id,
|
94
|
+
"officeBranchId" => :branch_id, "name" => :name
|
95
|
+
|
96
|
+
def self.all
|
97
|
+
@types ||= response_child(Office.get_types, "officeTypes", "type").collect {|attributes| Type.new(attributes)}
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.find_by_name name
|
101
|
+
Type.all.collect {|type| type if type.name == name }.compact.first
|
102
|
+
end
|
103
|
+
|
104
|
+
def offices
|
105
|
+
@offices ||= Office.find_all_by_type(self)
|
106
|
+
end
|
107
|
+
|
108
|
+
def offices_by_name names
|
109
|
+
names.collect {|name| offices.find {|office| office.name == name }}
|
110
|
+
end
|
111
|
+
|
112
|
+
def office_by_name name
|
113
|
+
offices_by_name([name]).first
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Official < Common
|
4
|
+
|
5
|
+
attr_accessor :id, :first_name, :nick_name, :middle_name, :last_name, :suffix, :title,
|
6
|
+
:election_parties, :office_parties, :district_id, :district_name, :state_id
|
7
|
+
|
8
|
+
attr_accessor :district, :office, :office_id, :party
|
9
|
+
|
10
|
+
set_attribute_map "candidateId" => :id, "firstName" => :first_name, "nickName" => :nick_name,
|
11
|
+
"middleName" => :middle_name, "lastName" => :last_name, "suffix" => :suffix,
|
12
|
+
"title" => :title, "electionParties" => :election_parties, "officeDistrictId" => :district_id,
|
13
|
+
"officeDistrictName" => :district_name, "officeParties" => :party, "officeStateId" => :state_id
|
14
|
+
|
15
|
+
def offices
|
16
|
+
offices = Official.response_child(Address.get_office(self.id), "address", "office")
|
17
|
+
(offices.is_a?(Array) ? offices : [offices]).collect {|office|
|
18
|
+
CandidateOffice.new(office)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"Official: " + [title, first_name, last_name].compact.join(' ')
|
24
|
+
end
|
25
|
+
|
26
|
+
def office_id
|
27
|
+
@office_id || (office.id if office)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find_by_district district
|
31
|
+
official = find_by_district_id district.id
|
32
|
+
official.district = district if official
|
33
|
+
official.office = district.office if official
|
34
|
+
official
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.find_by_district_id district_id
|
38
|
+
response = response_child(get_by_district(district_id), "candidateList", "candidate")
|
39
|
+
Official.new(response) unless response.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.find_by_office_id_and_state_id office_id, state_id
|
43
|
+
response = response_child(get_by_office_state(office_id, state_id), "candidateList", "candidate")
|
44
|
+
official = Official.new(response) unless response.empty?
|
45
|
+
official.office_id = office_id if official
|
46
|
+
official.state_id ||= state_id if official
|
47
|
+
official
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
def self.find_all_by_address address, city, state, zip
|
53
|
+
placemark = Geocoding.get("#{address} #{city}, #{state} #{zip}").first
|
54
|
+
|
55
|
+
return [] unless placemark
|
56
|
+
|
57
|
+
state ||= placemark.administrative_area
|
58
|
+
|
59
|
+
placemark ? find_all_by_state_and_latitude_and_longitude(state, placemark.latitude, placemark.longitude) : []
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.find_all_by_state_and_latitude_and_longitude state, latitude, longitude
|
63
|
+
response = Mcll4r.new.district_lookup(latitude, longitude)
|
64
|
+
response = response["response"] if response
|
65
|
+
|
66
|
+
state_upper = (response["state_upper"] || {})["district"]
|
67
|
+
state_lower = (response["state_lower"] || {})["district"]
|
68
|
+
|
69
|
+
find_all_state_wide_officials(state) + find_state_legislators(state, state_upper, state_lower, state_lower)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.find_all_state_wide_officials state_id
|
73
|
+
state_wide_office_names = ["Secretary of State", "Secretary of the Commonwealth", "Attorney General", "Secretary of Education",
|
74
|
+
"Education Secretary", "Treasurer", "Auditor"]
|
75
|
+
|
76
|
+
state_wide_type = Office::Type.find_by_name("State Wide")
|
77
|
+
|
78
|
+
state_wide_offices = state_wide_type ? state_wide_type.offices_by_name(state_wide_office_names) : []
|
79
|
+
|
80
|
+
state_wide_offices.collect { |office| office.official_by_state_id(state_id) }.compact
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.find_state_legislators state_id, senate_district, house_district, assembly_district
|
84
|
+
officials = []
|
85
|
+
|
86
|
+
state_leg_type = Office::Type.find_by_name("State Legislature")
|
87
|
+
|
88
|
+
{"State Senate" => senate_district,
|
89
|
+
"State House" => house_district,
|
90
|
+
"State Assembly" => assembly_district}.each do |office_name, district_number|
|
91
|
+
|
92
|
+
office = state_leg_type.office_by_name(office_name) if state_leg_type
|
93
|
+
|
94
|
+
district = office.district_by_state_id_and_number(state_id, district_number) if office
|
95
|
+
|
96
|
+
official = district.official if district
|
97
|
+
|
98
|
+
officials.push official if official
|
99
|
+
end
|
100
|
+
|
101
|
+
officials
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Returns a list of incumbents that fit the criteria
|
106
|
+
def self.get_by_office_state office_id, state_id = 'NA'
|
107
|
+
request("Officials.getByOfficeState", "officeId" => office_id, "stateId" => state_id)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Searches for incumbents with exact lastname matches
|
111
|
+
def self.get_by_lastname lastname
|
112
|
+
request("Officials.getByLastname", "lastName" => lastname)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Searches for incumbents with fuzzy lastname match
|
116
|
+
def self.get_by_levenstein lastname
|
117
|
+
request("Officials.getByLevenstein", "lastName" => lastname)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns incumbents in the provided election_id
|
121
|
+
def self.get_by_election election_id
|
122
|
+
request("Officials.getByElection", "electionId" => election_id)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns incumbents in the provided district_id
|
126
|
+
def self.get_by_district district_id
|
127
|
+
request("Officials.getByDistrict", "districtId" => district_id)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Phone < Common
|
4
|
+
|
5
|
+
attr_accessor :phone1, :phone2, :fax1, :fax2, :toll_free, :ttyd
|
6
|
+
|
7
|
+
set_attribute_map "phone1" => :phone1, "phone2" => :phone2, "fax1" => :fax1, "fax2" => :fax2,
|
8
|
+
"tollFree" => :toll_free, "ttyd" => :ttyd
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module VoteSmart
|
2
|
+
|
3
|
+
class Rating < Common
|
4
|
+
|
5
|
+
# Returns categories with ratings according to state_id(NA = fed)
|
6
|
+
def self.get_categories state_id = nil
|
7
|
+
request("Rating.getCategories", "stateId" => state_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns a list of SIGs with ratings in category and state
|
11
|
+
def self.get_sig_list category_id, state_id = 'NA'
|
12
|
+
request("Rating.getSigList", "categoryId" => category_id, "stateId" => state_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns detailed SIG information
|
16
|
+
def self.get_sig sig_id
|
17
|
+
result = request("Rating.getSig", "sigId" => sig_id)
|
18
|
+
# PVS return utf control codes for punction in descriptions
|
19
|
+
if result['sig']['description'].first == '"'
|
20
|
+
result['sig']['description'] = result['sig']['description'][1..-2]
|
21
|
+
end
|
22
|
+
result['sig']['description'] = result['sig']['description'].unpack("U*").map do |char|
|
23
|
+
case char
|
24
|
+
when 146 # 0092
|
25
|
+
39
|
26
|
+
when 148, 147 # 0093,4
|
27
|
+
34
|
28
|
+
when 150, 151 # 0096,7
|
29
|
+
45
|
30
|
+
else
|
31
|
+
char
|
32
|
+
end
|
33
|
+
end.pack("U*")
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns an SIG's rating on a specific candidate
|
38
|
+
def self.get_candidate_rating candidate_id, sig_id
|
39
|
+
request("Rating.getCandidateRating", "candidateId" => candidate_id, "sigId" => sig_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|