luigi-sunlight 0.2.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,16 @@
1
+ h3. 0.9.0 / 2009-03-15
2
+
3
+ * Warning: This release is not backwards-compatible!
4
+ * Change loading behavior of base functionality, works better with Rails and Merb
5
+ * Sunlight::SunlightObject is now Sunlight::Base
6
+ * For set up, Sunlight.api_key= is now Sunlight::Base.api_key=
7
+ * For set up, using "include 'Sunlight'" is no longer recommended
8
+ * Correct usage is Sunlight::Legislator.all_for(...) instead of just Legislator.all_for(...)
9
+ * Credit to Rue the Ghetto (rughetto on GitHub) and Eric Mill for inspiring the improvements above
10
+ * Add support for senate_class ("I", "II", or "III") and in_office (0 or 1) on Legislator
11
+ * Add support for Lobbyists, Filings, and Issues
12
+ * Huge credit to mindleak on GitHub for Lobbyist-related functionality
13
+
1
14
  h3. 0.2.0 / 2009-03-01
2
15
 
3
16
  * Add support for twitter_id and youtube_url on Legislator
@@ -36,16 +36,15 @@ h2. Set Up
36
36
 
37
37
  First, register for an API key "here":http://services.sunlightlabs.com/api/register/.
38
38
 
39
- Then, you'll want to stick the following lines somewhere in your Ruby environment.
39
+ Then, you'll want to stick the following lines somewhere in your Ruby environment. _Note, this set up changed slightly as of version 0.9.0:_
40
40
 
41
41
  <pre><code>
42
- require 'rubygems'
43
- require 'sunlight'
44
- include Sunlight
45
- Sunlight.api_key = 'yourapikeyfromtheurlabove'
42
+ require 'rubygems'
43
+ require 'sunlight'
44
+ Sunlight::Base.api_key = 'yourapikeyfromtheurlabove'
46
45
  </code></pre>
47
46
 
48
- If you're testing this out in IRB, you'll run them one at a time. If you're using Rails 2.1, stick them in a file called @sunlight.rb@ in @RAILS_ROOT/config/initializers@. They'll load on app startup.
47
+ If you're testing this out in IRB, you'll run them one at a time. If you're using Rails >=2.1, stick them in a file called @sunlight.rb@ in @RAILS_ROOT/config/initializers@. They'll load on app startup.
49
48
 
50
49
  h2. Usage
51
50
 
@@ -56,15 +55,15 @@ h3. Legislator
56
55
  Time to get to the good stuff. The most useful method is @Legislator#all_for@:
57
56
 
58
57
  <pre><code>
59
- congresspeople = Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
60
- senior_senator = congresspeople[:senior_senator]
61
- junior_senator = congresspeople[:junior_senator]
62
- representative = congresspeople[:representative]
63
-
64
- junior_senator.firstname # returns "Hillary"
65
- junior_senator.lastname # returns "Clinton"
66
- junior_senator.congress_office # returns "476 Russell Senate Office Building"
67
- junior_senator.phone # returns "202-224-4451"
58
+ congresspeople = Sunlight::Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
59
+ senior_senator = congresspeople[:senior_senator]
60
+ junior_senator = congresspeople[:junior_senator]
61
+ representative = congresspeople[:representative]
62
+
63
+ junior_senator.firstname # returns "Kirsten"
64
+ junior_senator.lastname # returns "Gillibrand"
65
+ junior_senator.congress_office # returns "531 Dirksen Senate Office Building"
66
+ junior_senator.phone # returns "202-224-4451"
68
67
  </code></pre>
69
68
 
70
69
  Note that you should make the best attempt to get a full street address, as that is geocoded behind the scenes into a lat/long pair. If all you have is a five-digit zip code, you should not use @Legislator#all_for@, instead opting for @Legislator#all_in_zipcode@ (see below). If you pass in a zip+4, then go ahead and use @Legislator#all_for@.
@@ -72,7 +71,7 @@ Note that you should make the best attempt to get a full street address, as that
72
71
  So @Legislator#all_for@ returns a hash of @Legislator@ objects, and the keys are @:senior_senator@, @:junior_senator@, and @:representative@. Make sure to review all the available fields from the "Sunlight Labs API":http://services.sunlightlabs.com/api/docs/legislators/. You can also pass in a lat/long pair:
73
72
 
74
73
  <pre><code>
75
- congresspeople = Legislator.all_for(:latitude => 33.876145, :longitude => -84.453789)
74
+ congresspeople = Sunlight::Legislator.all_for(:latitude => 33.876145, :longitude => -84.453789)
76
75
  </code></pre>
77
76
 
78
77
  This bypasses the geocoding necessary by the Google Maps API. For social networks and other applications with a User object, it makes sense to geocode the user's address up front and save the lat/long data in the local database. Then, use the lat/long pair instead of address, which cuts a substantial bit of time from the @Legislator#all_for@ request since the Google Maps API Geocoding function doesn't have to be called.
@@ -80,31 +79,30 @@ This bypasses the geocoding necessary by the Google Maps API. For social network
80
79
  Have a five-digit zip code only? You can use the @Legislator#all_in_zipcode@ method, but keep in mind that a single zip may have multiple U.S. Representatives, as congressional district lines frequently divide populous zip codes. Unlike @Legislator#all_for@, this method returns an array of legislators, and it'll be up to you to parse through them (there will be a senior senator, a junior senator, and one or more representatives).
81
80
 
82
81
  <pre><code>
83
- members_of_congress = Legislator.all_in_zipcode(90210)
84
-
82
+ members_of_congress = Sunlight::Legislator.all_in_zipcode(90210)
83
+
85
84
  members_of_congress.each do |member|
86
85
  # do stuff
87
86
  end
88
-
89
87
  </code></pre>
90
88
 
91
89
  You can also use the @Legislator#all_where@ method for searching based on available fields. Again, you'll get back an array of @Legislator@ objects:
92
90
 
93
91
  <pre><code>
94
- johns = Legislator.all_where(:firstname => "John")
95
- floridians = Legislator.all_where(:state => "FL")
96
- dudes = Legislator.all_where(:gender => "M")
92
+ johns = Sunlight::Legislator.all_where(:firstname => "John")
93
+ floridians = Sunlight::Legislator.all_where(:state => "FL")
94
+ dudes = Sunlight::Legislator.all_where(:gender => "M")
97
95
 
98
- johns.each do |john|
99
- # do stuff
100
- end
96
+ johns.each do |john|
97
+ # do stuff
98
+ end
101
99
  </code></pre>
102
100
 
103
101
  Lastly, to provide your users with a name search functionality, use @Legislator#search_by_name@, which uses fuzzy matching to compensate for nicknames and misspellings. So "Teddy Kennedey" (real name Edward Kennedy) and "Jack Murtha" (real name John Murtha) will return the correct matches. You can specify a higher confidence threshold (default set to 0.80) if you feel that the matches being returned aren't accurate enough. This also returns an array of @Legislator@ objects:
104
102
 
105
103
  <pre><code>
106
- legislators = Legislator.search_by_name("Teddy Kennedey")
107
- legislators = Legislator.search_by_name("Johnny Boy Kerry", 0.91)
104
+ legislators = Sunlight::Legislator.search_by_name("Teddy Kennedey")
105
+ legislators = Sunlight::Legislator.search_by_name("Johnny Boy Kerry", 0.91)
108
106
  </code></pre>
109
107
 
110
108
 
@@ -114,18 +112,48 @@ h3. District
114
112
  There's also the @District@ object. @District#get@ takes in either lat/long or an address and does it's best to return the correct Congressional District:
115
113
 
116
114
  <pre><code>
117
- district = District.get(:latitude => 33.876145, :longitude => -84.453789)
118
- district.state # returns "GA"
119
- district.number # returns "6"
120
-
121
- district = District.get(:address => "123 Fifth Ave New York, NY")
115
+ district = Sunlight::District.get(:latitude => 33.876145, :longitude => -84.453789)
116
+ district.state # returns "GA"
117
+ district.number # returns "6"
118
+
119
+ district = Sunlight::District.get(:address => "123 Fifth Ave New York, NY")
122
120
  </code></pre>
123
121
 
124
122
  Finally, two more methods, @District.all_from_zipcode@ and @District.zipcodes_in@, help you out when you want to get all districts in a given zip code, or if you want to get back all zip codes in a given district.
125
123
 
126
124
  <pre><code>
127
- districts = District.all_from_zipcode(90210) # returns array of District objects
128
- zipcodes = District.zipcodes_in("NY", "10") # returns array of zip codes as strings ["11201", "11202", "11203",...]
125
+ districts = Sunlight::District.all_from_zipcode(90210) # returns array of District objects
126
+ zipcodes = Sunlight::District.zipcodes_in("NY", "10") # returns array of zip codes as strings ["11201", "11202", "11203",...]
127
+ </code></pre>
128
+
129
+ h3. Lobbyists and Filings
130
+
131
+ Moving away from members of Congress, the Sunlight API also exposes data on @Lobbyists@, the organizations and companies they lobby on behalf of, and the @Issues@ they lobby on. Lobbyists must submit filings to the Senate Office of Public Records, and these are represented as @Filings@ in the API.
132
+
133
+ Like on the @Legislator@ object, the @Lobbyist@ object provides for fuzzy name search capability. However, because the universe of Lobbyists is much larger than Legislators, the confidence threshold defaults to 0.90 instead of 0.80, and also limits the search to Lobbyists who have filed in the current year. Both can be adjusted, and the method returns an array of @Lobbyist@ objects:
134
+
135
+ <pre><code>
136
+ lobbyists = Lobbyist.search("Nisha Thompsen")
137
+ lobbyists = Lobbyist.search("Michael Klein", 0.95, 2007)
138
+ </code></pre>
139
+
140
+ You can also use the @Filing@ object to get a specific filing record, where the unique identifier comes from the "Senate Office of Public Records":http://senate.gov/legislative/Public_Disclosure/LDA_reports.htm. The @Filing@ object will have an array of issues and lobbyists associated to it.
141
+
142
+ <pre><code>
143
+ filing = Sunlight::Filing.get("29D4D19E-CB7D-46D2-99F0-27FF15901A4C")
144
+ filing.issues.each { |issue| ... }
145
+ filing.lobbyists.each { |lobbyist| ... }
146
+ </code></pre>
147
+
148
+ If you have a client name (that is, the organization or company the lobbyist works for) or the registrant name (the lobbyist), then you can also find associated filings. To use the @all_where@ method, pass in a hash with @:client_name@, @:registrant_name@, and @:year@ as the keys. You must pass in @:client_name@ or @:registrant_name@.
149
+
150
+ <pre><code>
151
+ filings = Filing.all_where(:client_name => "SUNLIGHT FOUNDATION")
152
+ filings.each do |filing|
153
+ ...
154
+ filing.issues.each { |issue| ... }
155
+ filing.lobbyists.each { |issue| ... }
156
+ end
129
157
  </code></pre>
130
158
 
131
159
 
@@ -5,58 +5,4 @@ require 'ym4r/google_maps/geocoding'
5
5
  require 'net/http'
6
6
  include Ym4r::GoogleMaps
7
7
 
8
- module Sunlight
9
-
10
- API_URL = "http://services.sunlightlabs.com/api/"
11
- API_FORMAT = "json"
12
- attr_accessor :api_key
13
-
14
- # Houses general methods to work with the Sunlight and Google Maps APIs
15
- class SunlightObject
16
-
17
-
18
- # Constructs a Sunlight API-friendly URL
19
- def self.construct_url(api_method, params)
20
- if Sunlight.api_key == nil or Sunlight.api_key == ''
21
- raise "Failed to provide Sunlight API Key"
22
- else
23
- "#{API_URL}#{api_method}.#{API_FORMAT}?apikey=#{Sunlight.api_key}#{hash2get(params)}"
24
- end
25
- end
26
-
27
-
28
- # Converts a hash to a GET string
29
- def self.hash2get(h)
30
-
31
- get_string = ""
32
-
33
- h.each_pair do |key, value|
34
- get_string += "&#{key.to_s}=#{CGI::escape(value.to_s)}"
35
- end
36
-
37
- get_string
38
-
39
- end # def hash2get
40
-
41
-
42
- # Use the Net::HTTP and JSON libraries to make the API call
43
- #
44
- # Usage:
45
- # District.get_json_data("http://someurl.com") # returns Hash of data or nil
46
- def self.get_json_data(url)
47
-
48
- response = Net::HTTP.get_response(URI.parse(url))
49
- if response.class == Net::HTTPOK
50
- result = JSON.parse(response.body)
51
- else
52
- nil
53
- end
54
-
55
- end # self.get_json_data
56
-
57
-
58
- end # class SunlightObject
59
-
60
- end # module Sunlight
61
-
62
8
  Dir["#{File.dirname(__FILE__)}/sunlight/*.rb"].each { |source_file| require source_file }
@@ -0,0 +1,57 @@
1
+ module Sunlight
2
+
3
+ # Houses general methods to work with the Sunlight and Google Maps APIs
4
+ class Base
5
+
6
+ API_URL = "http://services.sunlightlabs.com/api/"
7
+ API_FORMAT = "json"
8
+ @@api_key = ''
9
+
10
+ def self.api_key
11
+ @@api_key
12
+ end
13
+
14
+ def self.api_key=(key)
15
+ @@api_key = key
16
+ end
17
+
18
+ # Constructs a Sunlight API-friendly URL
19
+ def self.construct_url(api_method, params)
20
+ if api_key == nil or api_key == ''
21
+ raise "Failed to provide Sunlight API Key"
22
+ else
23
+ "#{API_URL}#{api_method}.#{API_FORMAT}?apikey=#{api_key}#{hash2get(params)}"
24
+ end
25
+ end
26
+
27
+ # Converts a hash to a GET string
28
+ def self.hash2get(h)
29
+
30
+ get_string = ""
31
+
32
+ h.each_pair do |key, value|
33
+ get_string += "&#{key.to_s}=#{CGI::escape(value.to_s)}"
34
+ end
35
+
36
+ get_string
37
+
38
+ end # def hash2get
39
+
40
+ # Use the Net::HTTP and JSON libraries to make the API call
41
+ #
42
+ # Usage:
43
+ # Legislator::District.get_json_data("http://someurl.com") # returns Hash of data or nil
44
+ def self.get_json_data(url)
45
+
46
+ response = Net::HTTP.get_response(URI.parse(url))
47
+ if response.class == Net::HTTPOK
48
+ result = JSON.parse(response.body)
49
+ else
50
+ nil
51
+ end
52
+
53
+ end # self.get_json_data
54
+
55
+ end # class Base
56
+
57
+ end # module Sunlight
@@ -1,6 +1,6 @@
1
1
  module Sunlight
2
2
 
3
- class District < SunlightObject
3
+ class District < Base
4
4
 
5
5
  attr_accessor :state, :number
6
6
 
@@ -11,8 +11,8 @@ module Sunlight
11
11
 
12
12
 
13
13
  # Usage:
14
- # District.get(:latitude => 33.876145, :longitude => -84.453789) # returns one District object or nil
15
- # District.get(:address => "123 Fifth Ave New York, NY") # returns one District object or nil
14
+ # Sunlight::District.get(:latitude => 33.876145, :longitude => -84.453789) # returns one District object or nil
15
+ # Sunlight::District.get(:address => "123 Fifth Ave New York, NY") # returns one District object or nil
16
16
  #
17
17
  def self.get(params)
18
18
 
@@ -39,7 +39,7 @@ module Sunlight
39
39
 
40
40
 
41
41
  # Usage:
42
- # District.get_from_lat_long(-123, 123) # returns District object or nil
42
+ # Sunlight::District.get_from_lat_long(-123, 123) # returns District object or nil
43
43
  #
44
44
  def self.get_from_lat_long(latitude, longitude)
45
45
 
@@ -63,7 +63,7 @@ module Sunlight
63
63
 
64
64
 
65
65
  # Usage:
66
- # District.all_from_zipcode(90210) # returns array of District objects
66
+ # Sunlight::District.all_from_zipcode(90210) # returns array of District objects
67
67
  #
68
68
  def self.all_from_zipcode(zipcode)
69
69
 
@@ -87,7 +87,7 @@ module Sunlight
87
87
 
88
88
 
89
89
  # Usage:
90
- # District.zipcodes_in("NY", 29) # returns ["14009", "14024", "14029", ...]
90
+ # Sunlight::District.zipcodes_in("NY", 29) # returns ["14009", "14024", "14029", ...]
91
91
  #
92
92
  def self.zipcodes_in(state, number)
93
93
 
@@ -0,0 +1,119 @@
1
+ module Sunlight
2
+
3
+ class Filing < Base
4
+ attr_accessor :filing_id, :filing_period, :filing_date, :filing_amount,
5
+ :filing_year, :filing_type, :filing_pdf, :client_senate_id,
6
+ :client_name, :client_country, :client_state,
7
+ :client_ppb_country, :client_ppb_state, :client_description,
8
+ :client_contact_firstname, :client_contact_middlename,
9
+ :client_contact_lastname, :client_contact_suffix,
10
+ :registrant_senate_id, :registrant_name, :registrant_address,
11
+ :registrant_description, :registrant_country,
12
+ :registrant_ppb_country, :lobbyists, :issues
13
+
14
+ # Takes in a hash where the keys are strings (the format passed in by the JSON parser)
15
+ #
16
+ def initialize(params)
17
+ params.each do |key, value|
18
+ instance_variable_set("@#{key}", value) if Filing.instance_methods.include? key
19
+ end
20
+ end
21
+
22
+ #
23
+ # Get a filing based on filing ID.
24
+ #
25
+ # See the API documentation:
26
+ #
27
+ # http://wiki.sunlightlabs.com/index.php/Lobbyists.getFiling
28
+ #
29
+ # Returns:
30
+ #
31
+ # A Filing and corresponding Lobbyists and Issues matching
32
+ # the given ID, or nil if one wasn't found.
33
+ #
34
+ # Usage:
35
+ #
36
+ # filing = Sunlight::Filing.get("29D4D19E-CB7D-46D2-99F0-27FF15901A4C")
37
+ # filing.issues.each { |issue| ... }
38
+ # filing.lobbyists.each { |lobbyist| ... }
39
+ #
40
+ def self.get(id)
41
+ url = construct_url("lobbyists.getFiling", :id => id)
42
+
43
+ if (response = get_json_data(url))
44
+ if (f = response["response"]["filing"])
45
+ filing = Filing.new(f)
46
+ filing.lobbyists = filing.lobbyists.map do |lobbyist|
47
+ Lobbyist.new(lobbyist["lobbyist"])
48
+ end
49
+ filing.issues = filing.issues.map do |issue|
50
+ Issue.new(issue["issue"])
51
+ end
52
+ filing
53
+ else
54
+ nil
55
+ end
56
+ else
57
+ nil
58
+ end
59
+ end
60
+
61
+ #
62
+ # Search the filing database. At least one of client_name or
63
+ # registrant_name must be provided, along with an optional year.
64
+ # Note that year is recommended, as the full data set dating back
65
+ # to 1999 may be enormous.
66
+ #
67
+ # See the API documentation:
68
+ #
69
+ # http://wiki.sunlightlabs.com/index.php/Lobbyists.getFilingList
70
+ #
71
+ # Returns:
72
+ #
73
+ # An array of Filing objects that match the conditions
74
+ #
75
+ # Usage:
76
+ #
77
+ # filings = Filing.all_where(:client_name => "SUNLIGHT FOUNDATION")
78
+ # filings.each do |filing|
79
+ # ...
80
+ # filing.issues.each { |issue| ... }
81
+ # filing.lobbyists.each { |issue| ... }
82
+ # end
83
+ #
84
+ def self.all_where(params)
85
+ if params[:client_name].nil? and params[:registrant_name].nil?
86
+ nil
87
+ else
88
+ url = construct_url("lobbyists.getFilingList", params)
89
+
90
+ if (response = get_json_data(url))
91
+ filings = []
92
+
93
+ response["response"]["filings"].each do |result|
94
+ filing = Filing.new(result["filing"])
95
+
96
+ filing.lobbyists = filing.lobbyists.map do |lobbyist|
97
+ Lobbyist.new(lobbyist["lobbyist"])
98
+ end
99
+ filing.issues = filing.issues.map do |issue|
100
+ Issue.new(issue["issue"])
101
+ end
102
+
103
+ filings << filing
104
+ end
105
+
106
+ if filings.empty?
107
+ nil
108
+ else
109
+ filings
110
+ end
111
+ else
112
+ nil
113
+ end
114
+ end # if params
115
+ end # def self.all_where
116
+
117
+ end # class Filing
118
+
119
+ end # module Sunlight
@@ -0,0 +1,15 @@
1
+ module Sunlight
2
+
3
+ class Issue < Base
4
+ attr_accessor :code, :specific_issue
5
+
6
+ # Takes in a hash where the keys are strings (the format passed in by the JSON parser)
7
+ #
8
+ def initialize(params)
9
+ params.each do |key, value|
10
+ instance_variable_set("@#{key}", value) if Issue.instance_methods.include? key
11
+ end
12
+ end
13
+ end
14
+
15
+ end
@@ -1,13 +1,13 @@
1
1
  module Sunlight
2
2
 
3
- class Legislator < SunlightObject
3
+ class Legislator < Base
4
4
 
5
5
 
6
6
  attr_accessor :title, :firstname, :middlename, :lastname, :name_suffix, :nickname,
7
7
  :party, :state, :district, :gender, :phone, :fax, :website, :webform,
8
8
  :email, :congress_office, :bioguide_id, :votesmart_id, :fec_id,
9
9
  :govtrack_id, :crp_id, :event_id, :congresspedia_url, :youtube_url,
10
- :twitter_id, :fuzzy_score
10
+ :twitter_id, :fuzzy_score, :in_office, :senate_class
11
11
 
12
12
  # Takes in a hash where the keys are strings (the format passed in by the JSON parser)
13
13
  #
@@ -18,7 +18,6 @@ module Sunlight
18
18
  end
19
19
 
20
20
 
21
-
22
21
  #
23
22
  # Useful for getting the exact Legislators for a given district.
24
23
  #
@@ -35,8 +34,8 @@ module Sunlight
35
34
  # junior = officials[:junior_senator]
36
35
  # rep = officials[:representative]
37
36
  #
38
- # Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
39
- # Legislator.all_for(:address => "90210") # it'll work, but use all_in_zip instead
37
+ # Sunlight::Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
38
+ # Sunlight::Legislator.all_for(:address => "90210") # it'll work, but use all_in_zip instead
40
39
  #
41
40
  def self.all_for(params)
42
41
 
@@ -57,7 +56,7 @@ module Sunlight
57
56
  #
58
57
  # Usage:
59
58
  #
60
- # officials = Legislator.all_in_district(District.new("NJ", "7"))
59
+ # officials = Sunlight::Legislator.all_in_district(District.new("NJ", "7"))
61
60
  #
62
61
  def self.all_in_district(district)
63
62
 
@@ -82,9 +81,9 @@ module Sunlight
82
81
  #
83
82
  # Usage:
84
83
  #
85
- # johns = Legislator.all_where(:firstname => "John")
86
- # floridians = Legislator.all_where(:state => "FL")
87
- # dudes = Legislator.all_where(:gender => "M")
84
+ # johns = Sunlight::Legislator.all_where(:firstname => "John")
85
+ # floridians = Sunlight::Legislator.all_where(:state => "FL")
86
+ # dudes = Sunlight::Legislator.all_where(:gender => "M")
88
87
  #
89
88
  def self.all_where(params)
90
89
 
@@ -119,7 +118,7 @@ module Sunlight
119
118
  #
120
119
  # Usage:
121
120
  #
122
- # legislators = Legislator.all_in_zipcode(90210)
121
+ # legislators = Sunlight::Legislator.all_in_zipcode(90210)
123
122
  #
124
123
  def self.all_in_zipcode(zipcode)
125
124
 
@@ -156,8 +155,8 @@ module Sunlight
156
155
  #
157
156
  # Usage:
158
157
  #
159
- # legislators = Legislator.search_by_name("Teddy Kennedey")
160
- # legislators = Legislator.search_by_name("Johnny Kerry", 0.9)
158
+ # legislators = Sunlight::Legislator.search_by_name("Teddy Kennedey")
159
+ # legislators = Sunlight::Legislator.search_by_name("Johnny Kerry", 0.9)
161
160
  #
162
161
  def self.search_by_name(name, threshold='0.8')
163
162
 
@@ -0,0 +1,63 @@
1
+ module Sunlight
2
+
3
+ class Lobbyist < Base
4
+ attr_accessor :firstname, :middlename, :lastname, :suffix,
5
+ :official_position, :filings, :fuzzy_score
6
+
7
+ # Takes in a hash where the keys are strings (the format passed in by the JSON parser)
8
+ #
9
+ def initialize(params)
10
+ params.each do |key, value|
11
+ instance_variable_set("@#{key}", value) if Lobbyist.instance_methods.include? key
12
+ end
13
+ end
14
+
15
+ #
16
+ # Fuzzy name searching of lobbyists. Returns possible matching Lobbyists
17
+ # along with a confidence score. Confidence scores below 0.8
18
+ # mean the lobbyist should not be used.
19
+ #
20
+ # See the API documentation:
21
+ #
22
+ # http://wiki.sunlightlabs.com/index.php/Lobbyists.search
23
+ #
24
+ # Returns:
25
+ #
26
+ # An array of Lobbyists, with the fuzzy_score set as an attribute
27
+ #
28
+ # Usage:
29
+ #
30
+ # lobbyists = Lobbyist.search("Nisha Thompsen")
31
+ # lobbyists = Lobbyist.search("Michael Klein", 0.95, 2007)
32
+ #
33
+ def self.search_by_name(name, threshold=0.9, year=Time.now.year)
34
+
35
+ url = construct_url("lobbyists.search", :name => name, :threshold => threshold, :year => year)
36
+
37
+ if (results = get_json_data(url))
38
+ lobbyists = []
39
+ results["response"]["results"].each do |result|
40
+ if result
41
+ lobbyist = Lobbyist.new(result["result"]["lobbyist"])
42
+ fuzzy_score = result["result"]["score"]
43
+
44
+ if threshold.to_f < fuzzy_score.to_f
45
+ lobbyist.fuzzy_score = fuzzy_score.to_f
46
+ lobbyists << lobbyist
47
+ end
48
+ end
49
+ end
50
+
51
+ if lobbyists.empty?
52
+ nil
53
+ else
54
+ lobbyists
55
+ end
56
+
57
+ else
58
+ nil
59
+ end
60
+ end # def self.search
61
+ end # class Lobbyist
62
+
63
+ end
@@ -1,13 +1,15 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "sunlight"
3
- s.version = "0.2.0"
4
- s.date = "2009-03-01"
3
+ s.version = "0.9.0"
4
+ s.date = "2009-03-15"
5
5
  s.summary = "Library for accessing the Sunlight Labs API."
6
6
  s.email = "luigi.montanez@gmail.com"
7
7
  s.homepage = "http://github.com/luigi/sunlight"
8
8
  s.authors = ["Luigi Montanez"]
9
- s.files = ['sunlight.gemspec', 'lib/sunlight.rb', 'lib/sunlight/district.rb',
10
- 'lib/sunlight/legislator.rb', 'README.textile', 'CHANGES.textile']
9
+ s.files = ['sunlight.gemspec', 'lib/sunlight.rb', 'lib/sunlight/base.rb',
10
+ 'lib/sunlight/district.rb', 'lib/sunlight/legislator.rb',
11
+ 'lib/sunlight/filing.rb', 'lib/sunlight/issue.rb',
12
+ 'lib/sunlight/lobbyist.rb','README.textile', 'CHANGES.textile']
11
13
  s.add_dependency("json", [">= 1.1.3"])
12
14
  s.add_dependency("ym4r", [">= 0.6.1"])
13
15
  s.has_rdoc = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luigi-sunlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luigi Montanez
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-01 00:00:00 -08:00
12
+ date: 2009-03-15 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -43,8 +43,12 @@ extra_rdoc_files: []
43
43
  files:
44
44
  - sunlight.gemspec
45
45
  - lib/sunlight.rb
46
+ - lib/sunlight/base.rb
46
47
  - lib/sunlight/district.rb
47
48
  - lib/sunlight/legislator.rb
49
+ - lib/sunlight/filing.rb
50
+ - lib/sunlight/issue.rb
51
+ - lib/sunlight/lobbyist.rb
48
52
  - README.textile
49
53
  - CHANGES.textile
50
54
  has_rdoc: true