votesmart 0.3.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.
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