votesmart 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +1 -0
  2. data/History.txt +20 -0
  3. data/README.rdoc +48 -0
  4. data/Rakefile +45 -0
  5. data/VERSION.yml +4 -0
  6. data/lib/mcll4r/MIT-LICENSE +20 -0
  7. data/lib/mcll4r/README +19 -0
  8. data/lib/mcll4r/mcll4r.rb +24 -0
  9. data/lib/mcll4r/mcll4r_test.rb +35 -0
  10. data/lib/vote_smart.rb +22 -0
  11. data/lib/vote_smart/address.rb +42 -0
  12. data/lib/vote_smart/candidate.rb +32 -0
  13. data/lib/vote_smart/candidate_bio.rb +16 -0
  14. data/lib/vote_smart/candidate_office.rb +15 -0
  15. data/lib/vote_smart/committee.rb +23 -0
  16. data/lib/vote_smart/common.rb +97 -0
  17. data/lib/vote_smart/district.rb +38 -0
  18. data/lib/vote_smart/election.rb +21 -0
  19. data/lib/vote_smart/leadership.rb +16 -0
  20. data/lib/vote_smart/local.rb +21 -0
  21. data/lib/vote_smart/measure.rb +16 -0
  22. data/lib/vote_smart/notes.rb +11 -0
  23. data/lib/vote_smart/npat.rb +11 -0
  24. data/lib/vote_smart/office.rb +119 -0
  25. data/lib/vote_smart/official.rb +131 -0
  26. data/lib/vote_smart/phone.rb +12 -0
  27. data/lib/vote_smart/rating.rb +43 -0
  28. data/lib/vote_smart/state.rb +29 -0
  29. data/lib/vote_smart/vote.rb +70 -0
  30. data/lib/votesmart.rb +1 -0
  31. data/script/autospec +6 -0
  32. data/script/console +10 -0
  33. data/script/destroy +14 -0
  34. data/script/generate +14 -0
  35. data/script/is_gem_built +40 -0
  36. data/spec/responses/Address.get_office.106446.js +1 -0
  37. data/spec/responses/Address.get_office.1721.js +1 -0
  38. data/spec/responses/District.get_by_office_state.7.GA.js +1 -0
  39. data/spec/responses/District.get_by_office_state.8.GA.js +1 -0
  40. data/spec/responses/District.get_by_office_state.9.GA.js +1 -0
  41. data/spec/responses/Office.get_offices_by_type.C.js +1 -0
  42. data/spec/responses/Office.get_offices_by_type.L.js +1 -0
  43. data/spec/responses/Office.get_offices_by_type.P.js +1 -0
  44. data/spec/responses/Office.get_offices_by_type.S.js +1 -0
  45. data/spec/responses/Office.get_types.js +1 -0
  46. data/spec/responses/Official.get_by_district.20451.js +1 -0
  47. data/spec/responses/Official.get_by_district.20689.js +1 -0
  48. data/spec/responses/Official.get_by_district.21397.js +1 -0
  49. data/spec/responses/Official.get_by_district.21946.js +1 -0
  50. data/spec/responses/Official.get_by_office_state.12.CO.js +1 -0
  51. data/spec/responses/Official.get_by_office_state.12.GA.js +1 -0
  52. data/spec/responses/Official.get_by_office_state.13.GA.js +1 -0
  53. data/spec/responses/Official.get_by_office_state.33.GA.js +1 -0
  54. data/spec/responses/Official.get_by_office_state.42.GA.js +1 -0
  55. data/spec/responses/Official.get_by_office_state.44.GA.js +1 -0
  56. data/spec/responses/Official.get_by_office_state.45.GA.js +1 -0
  57. data/spec/responses/Official.get_by_office_state.53.GA.js +1 -0
  58. data/spec/responses/Rating.get_sig.1863.js +1 -0
  59. data/spec/responses/State.get_state.GA.js +1 -0
  60. data/spec/responses/State.get_state_ids.js +1 -0
  61. data/spec/responses/authorization_failed.js +1 -0
  62. data/spec/spec_helper.rb +98 -0
  63. data/spec/vote_smart/district_spec.rb +36 -0
  64. data/spec/vote_smart/office_spec.rb +96 -0
  65. data/spec/vote_smart/official_spec.rb +56 -0
  66. data/spec/vote_smart/rating_spec.rb +15 -0
  67. data/spec/vote_smart/state_spec.rb +28 -0
  68. data/tasks/spec_json.rake +64 -0
  69. data/votesmart.gemspec +116 -0
  70. 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,11 @@
1
+ module VoteSmart
2
+
3
+ class Notes < Common
4
+
5
+ attr_accessor :contact_name, :contact_title, :note
6
+
7
+ set_attribute_map "contactName" => :contact_name, "contactTitle" => :contact_title, "note" => :note
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module VoteSmart
2
+
3
+ class Npat < Common
4
+
5
+ # Returns the most recent NPAT filled out by a candidate
6
+ def self.get_npat can_id
7
+ request("Npat.getNpat", "candidateId" => can_id)
8
+ end
9
+
10
+ end
11
+ 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