govkit 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem "active_support"
5
+ gem "activesupport", :require => 'active_support'
6
6
  gem "nokogiri"
7
7
  gem "httparty"
8
8
  gem "i18n"
@@ -10,4 +10,4 @@ gem "i18n"
10
10
  group :test do
11
11
  gem "rspec"
12
12
  gem "fakeweb"
13
- end
13
+ end
data/README.md CHANGED
@@ -20,6 +20,14 @@ Add govkit to your environment.rb or Gemfile
20
20
 
21
21
  Run <code>rails generate govkit</code> (Rails 3.x) or <code>script/generate govkit</code> (Rails 2.x) to copy a config file into <code>config/initializers/govkit.rb</code>. You will need to add your API keys to this config file.
22
22
 
23
+ Outside of Rails you can configure your API keys like so:
24
+
25
+ >> GovKit.configure do |config|
26
+ >> config.sunlight_apikey = 'YOUR_SUNLIGHT_API_KEY'
27
+ >> config.votesmart_apikey = 'YOUR_VOTESMART_API_KEY'
28
+ >> config.ftm_apikey = 'YOUR_FTM_API_KEY'
29
+ >> end
30
+
23
31
  # Usage Examples
24
32
 
25
33
  >> GovKit::OpenStates::State.find_by_abbreviation('CA')
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.1
1
+ 0.7.2
@@ -8,6 +8,10 @@ class GovkitGenerator < Rails::Generator::Base
8
8
  record do |m|
9
9
  m.directory File.join('config', 'initializers')
10
10
  m.template 'govkit.rb', File.join('config', 'initializers', 'govkit.rb')
11
+ m.directory File.join('app', 'models')
12
+ m.template 'mention.rb', File.join('app', 'models', 'mention.rb')
13
+ m.directory File.join('db', 'migrate')
14
+ m.template 'create_mentions.rb', File.join('db', 'migrate', 'create_mentions.rb')
11
15
  end
12
16
  end
13
17
 
@@ -0,0 +1,21 @@
1
+ class CreateMentions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :mentions, :force => true do |t|
4
+ t.string "url", :limit => 8000
5
+ t.string "excerpt", :limit => 4000
6
+ t.string "title", :limit => 1000
7
+ t.string "source"
8
+ t.datetime "date"
9
+ t.float "weight"
10
+ t.integer "owner_id"
11
+ t.string "owner_type"
12
+ t.string "search_source"
13
+ t.datetime "created_at"
14
+ t.datetime "updated_at"
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :mentions
20
+ end
21
+ end
@@ -11,13 +11,9 @@ if defined? GovKit
11
11
  # API key for NIMSP. Request one here:
12
12
  # http://www.followthemoney.org/membership/settings.phtml
13
13
  config.ftm_apikey = 'YOUR_FTM_API_KEY'
14
-
15
- # Api key for OpenCongress
16
- # http://www.opencongress.org/api
17
- config.opencongress_apikey = 'YOUR_OPENCONGRESS_API_KEY'
18
14
 
19
15
  # Technorati API key
20
- config.technorati_apikey = 'YOUR_TECHNORATI_APIKEY'
16
+ # config.technorati_apikey = 'YOUR_TECHNORATI_APIKEY'
21
17
 
22
18
  # Bing App ID
23
19
  config.bing_appid = 'YOUR_BING_APPID'
@@ -0,0 +1,15 @@
1
+ # A model to contain mentions of the :owner in the media
2
+ class Mention < ActiveRecord::Base
3
+ belongs_to :owner, :polymorphic => true
4
+
5
+ scope :since, lambda { |d| where(["mentions.date > ?", d]) }
6
+
7
+ # Returns the mentions in JSON form
8
+ #
9
+ # @params [Hash] A hash of options
10
+ # @return The mentions in JSON form
11
+ def as_json(opts = {})
12
+ default_opts = {:except => [:owner_id, :owner_type]}
13
+ super(default_opts.merge(opts))
14
+ end
15
+ end
data/govkit.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{govkit}
8
- s.version = "0.7.1"
8
+ s.version = "0.7.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Participatory Politics Foundation", "Srinivas Aki", "Carl Tashian"]
12
- s.date = %q{2011-06-30}
12
+ s.date = %q{2012-01-23}
13
13
  s.description = %q{Govkit lets you quickly get encapsulated Ruby objects for common open government APIs. We're starting with Sunlight's Open States API and the Project Vote Smart API.}
14
14
  s.email = %q{develop@opencongress.org}
15
15
  s.extra_rdoc_files = [
@@ -26,11 +26,15 @@ Gem::Specification.new do |s|
26
26
  "USAGE",
27
27
  "VERSION",
28
28
  "generators/govkit/govkit_generator.rb",
29
+ "generators/govkit/templates/create_mentions.rb",
29
30
  "generators/govkit/templates/govkit.rb",
31
+ "generators/govkit/templates/mention.rb",
30
32
  "govkit.gemspec",
31
33
  "init.rb",
32
34
  "lib/generators/govkit/govkit_generator.rb",
35
+ "lib/generators/govkit/templates/create_mentions.rb",
33
36
  "lib/generators/govkit/templates/govkit.rb",
37
+ "lib/generators/govkit/templates/mention.rb",
34
38
  "lib/gov_kit.rb",
35
39
  "lib/gov_kit/acts_as_noteworthy.rb",
36
40
  "lib/gov_kit/configuration.rb",
@@ -62,6 +66,10 @@ Gem::Specification.new do |s|
62
66
  "spec/fixtures/follow_the_money/business-page1.response",
63
67
  "spec/fixtures/follow_the_money/contribution.response",
64
68
  "spec/fixtures/follow_the_money/unauthorized.response",
69
+ "spec/fixtures/open_congress/501.response",
70
+ "spec/fixtures/open_congress/bill.response",
71
+ "spec/fixtures/open_congress/empty.response",
72
+ "spec/fixtures/open_congress/fl01.response",
65
73
  "spec/fixtures/open_congress/person.response",
66
74
  "spec/fixtures/open_states/401.response",
67
75
  "spec/fixtures/open_states/404.response",
@@ -89,15 +97,24 @@ Gem::Specification.new do |s|
89
97
  ]
90
98
  s.homepage = %q{http://github.com/opengovernment/govkit}
91
99
  s.require_paths = ["lib"]
92
- s.rubygems_version = %q{1.6.2}
100
+ s.rubygems_version = %q{1.3.6}
93
101
  s.summary = %q{Simple access to open government APIs around the web}
102
+ s.test_files = [
103
+ "spec/follow_the_money_spec.rb",
104
+ "spec/open_congress_spec.rb",
105
+ "spec/open_states_spec.rb",
106
+ "spec/search_engines_spec.rb",
107
+ "spec/spec_helper.rb",
108
+ "spec/transparency_data_spec.rb"
109
+ ]
94
110
 
95
111
  if s.respond_to? :specification_version then
112
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
96
113
  s.specification_version = 3
97
114
 
98
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
115
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
99
116
  s.add_runtime_dependency(%q<govkit>, [">= 0"])
100
- s.add_runtime_dependency(%q<active_support>, [">= 0"])
117
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
101
118
  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
102
119
  s.add_runtime_dependency(%q<httparty>, [">= 0"])
103
120
  s.add_runtime_dependency(%q<i18n>, [">= 0"])
@@ -107,7 +124,7 @@ Gem::Specification.new do |s|
107
124
  s.add_runtime_dependency(%q<fastercsv>, [">= 1.5.3"])
108
125
  else
109
126
  s.add_dependency(%q<govkit>, [">= 0"])
110
- s.add_dependency(%q<active_support>, [">= 0"])
127
+ s.add_dependency(%q<activesupport>, [">= 0"])
111
128
  s.add_dependency(%q<nokogiri>, [">= 0"])
112
129
  s.add_dependency(%q<httparty>, [">= 0"])
113
130
  s.add_dependency(%q<i18n>, [">= 0"])
@@ -118,7 +135,7 @@ Gem::Specification.new do |s|
118
135
  end
119
136
  else
120
137
  s.add_dependency(%q<govkit>, [">= 0"])
121
- s.add_dependency(%q<active_support>, [">= 0"])
138
+ s.add_dependency(%q<activesupport>, [">= 0"])
122
139
  s.add_dependency(%q<nokogiri>, [">= 0"])
123
140
  s.add_dependency(%q<httparty>, [">= 0"])
124
141
  s.add_dependency(%q<i18n>, [">= 0"])
@@ -1,17 +1,21 @@
1
1
  require 'rails/generators'
2
2
 
3
+ # Generator to setup rails app for using GovKit
3
4
  class GovkitGenerator < Rails::Generators::Base
4
5
 
5
6
  def initialize(*runtime_args)
6
7
  super
7
8
  end
8
9
 
9
- desc "Copies a config initializer to config/initializers/govkit.rb"
10
+ desc "Copies files necessary to use govkit"
10
11
 
11
12
  source_root File.join(File.dirname(__FILE__), 'templates')
12
-
13
+
14
+ # Copies the files necessary to use govkit (initializer, migrations, and models)
13
15
  def copy_initializer_file
14
16
  copy_file 'govkit.rb', File.join('config', 'initializers', 'govkit.rb')
17
+ copy_file 'mention.rb', File.join('app', 'models', 'mention.rb')
18
+ copy_file 'create_mentions.rb', File.join('db', 'migrate', "#{ Time.now.utc.strftime "%Y%m%d%H%M%S" }create_mentions.rb")
15
19
  end
16
20
 
17
21
  end
@@ -0,0 +1,21 @@
1
+ class CreateMentions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :mentions, :force => true do |t|
4
+ t.string "url", :limit => 8000
5
+ t.string "excerpt", :limit => 4000
6
+ t.string "title", :limit => 1000
7
+ t.string "source"
8
+ t.datetime "date"
9
+ t.float "weight"
10
+ t.integer "owner_id"
11
+ t.string "owner_type"
12
+ t.string "search_source"
13
+ t.datetime "created_at"
14
+ t.datetime "updated_at"
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :mentions
20
+ end
21
+ end
@@ -11,13 +11,12 @@ if defined? GovKit
11
11
  # API key for NIMSP. Request one here:
12
12
  # http://www.followthemoney.org/membership/settings.phtml
13
13
  config.ftm_apikey = 'YOUR_FTM_API_KEY'
14
-
15
- # Api key for OpenCongress
16
- # http://www.opencongress.org/api
17
- config.opencongress_apikey = 'YOUR_OPENCONGRESS_API_KEY'
18
14
 
19
15
  # Technorati API key
20
- config.technorati_apikey = 'YOUR_TECHNORATI_APIKEY'
16
+ # config.technorati_apikey = 'YOUR_TECHNORATI_APIKEY'
17
+
18
+ # Bing App ID
19
+ config.bing_appid = 'YOUR_BING_APPID'
21
20
 
22
21
  # Other things you could set here include alternate URLs for
23
22
  # the APIs. See GovKit::Configuration for available attributes.
@@ -0,0 +1,15 @@
1
+ # A model to contain mentions of the :owner in the media
2
+ class Mention < ActiveRecord::Base
3
+ belongs_to :owner, :polymorphic => true
4
+
5
+ scope :since, lambda { |d| where(["mentions.date > ?", d]) }
6
+
7
+ # Returns the mentions in JSON form
8
+ #
9
+ # @params [Hash] A hash of options
10
+ # @return The mentions in JSON form
11
+ def as_json(opts = {})
12
+ default_opts = {:except => [:owner_id, :owner_type]}
13
+ super(default_opts.merge(opts))
14
+ end
15
+ end
@@ -4,7 +4,11 @@ module GovKit::ActsAsNoteworthy
4
4
  base.extend ActMethods
5
5
  end
6
6
 
7
+ # Module to make a rails model act as a noteworthy object, linking it to govkit's mention model
7
8
  module ActMethods
9
+ # Sets up the relationship between the model and the mention model
10
+ #
11
+ # @param [Hash] opts a hash of options to be used by the relationship
8
12
  def acts_as_noteworthy(options={})
9
13
  class_inheritable_accessor :options
10
14
  self.options = options
@@ -16,7 +20,7 @@ module GovKit::ActsAsNoteworthy
16
20
  with_options :as => :owner, :class_name => "Mention" do |c|
17
21
  c.has_many :google_news_mentions, :conditions => {:search_source => "Google News"}, :order => 'date desc'
18
22
  c.has_many :google_blog_mentions, :conditions => {:search_source => "Google Blogs"}, :order => 'date desc'
19
- c.has_many :technorati_mentions, :conditions => {:search_source => "Technorati"}, :order => 'date desc'
23
+ # c.has_many :technorati_mentions, :conditions => {:search_source => "Technorati"}, :order => 'date desc'
20
24
  c.has_many :bing_mentions, :conditions => {:search_source => "Bing"}, :order => 'date desc'
21
25
  end
22
26
  end
@@ -29,9 +33,12 @@ module GovKit::ActsAsNoteworthy
29
33
 
30
34
  module ClassMethods
31
35
  end
32
-
36
+
37
+ # A module that adds methods to individual instances of the noteworthy class.
33
38
  module InstanceMethods
34
-
39
+ # Generates the raw mentions to be loaded into the Mention objects
40
+ #
41
+ # @return [Hash] a hash of all the mentions found of the object in question.
35
42
  def raw_mentions
36
43
  opts = self.options.clone
37
44
  attributes = opts.delete(:with)
@@ -10,7 +10,7 @@ module GovKit
10
10
  attr_accessor :bing_appid, :bing_base_url
11
11
 
12
12
  def initialize
13
- @openstates_apikey = @votesmart_apikey = @ftm_apikey = ''
13
+ @sunlight_apikey = @openstates_apikey = @votesmart_apikey = @ftm_apikey = ''
14
14
  @openstates_base_url = 'openstates.sunlightlabs.com/api/v1/'
15
15
  @transparency_data_base_url = 'transparencydata.com/api/1.0/'
16
16
  @votesmart_base_url = 'api.votesmart.org/'
@@ -25,20 +25,34 @@ module GovKit
25
25
  # Permant home for contribution category mappings
26
26
  @transparency_data_categories_url = 'http://assets.transparencydata.org.s3.amazonaws.com/docs/catcodes.csv'
27
27
  end
28
+
29
+ def opencongress_apikey= key
30
+ warn "[DEPRECATION] OpenCongress no longer requires an API Key. Ability to set it will be removed in future versions"
31
+ @opencongress_apikey = key
32
+ end
33
+
34
+ def openstates_apikey= key
35
+ warn "[DEPRECATION] Use sunlight_apikey instead of openstates_apikey. Ability to set it will be removed in future versions"
36
+ @sunlight_apikey = key
37
+ end
28
38
  end
29
39
 
30
40
  class << self
31
41
  attr_accessor :configuration
42
+
43
+ def configuration
44
+ @configuration = Configuration.new if @configuration.nil?
45
+ @configuration
46
+ end
32
47
  end
33
48
 
34
49
  # Configure GovKit in config/initializers/govkit.rb
35
50
  #
36
51
  # @example
37
52
  # GovKit.configure do |config|
38
- # config.openstates_apikey = ''
53
+ # config.sunlight_apikey = ''
39
54
  # end
40
55
  def self.configure
41
- self.configuration ||= Configuration.new
42
56
  yield(configuration)
43
57
  end
44
58
  end
@@ -1,8 +1,23 @@
1
1
  module GovKit
2
+
3
+ # Subclass of {Resource} for FollowTheMoney data. This
4
+ # is subclassed further for each of the different types of record
5
+ # returned by FollowTheMoney.
6
+ #
7
+ # For the details on the FollowTheMoney queries, see {http://www.followthemoney.org/services/methods.phtml the FollowTheMoney API documentation}.
2
8
  class FollowTheMoneyResource < Resource
3
9
  default_params :key => GovKit::configuration.ftm_apikey
4
10
  base_uri GovKit::configuration.ftm_base_url
5
11
 
12
+ # Common method used by subclasses to get data from the service.
13
+ #
14
+ # @return [Nokogiri::XML::Document] a {http://nokogiri.org/Nokogiri/HTML/Document.html Nokogiri XML::Document} object
15
+ # @param [String] path query path that specifies the required data
16
+ # @param [Hash] options query options
17
+ #
18
+ # @example
19
+ # doc = get_xml("/base_level.industries.list.php", :query => {:page => page_num})
20
+ #
6
21
  def self.get_xml(path, options)
7
22
  doc = Nokogiri::XML(get(path, options))
8
23
 
@@ -25,15 +40,27 @@ module GovKit
25
40
  doc
26
41
  end
27
42
 
43
+ # Convert the hash array returned by Nokogiri, which has Nokogiri::XML::Attr objects as values,
44
+ # to an array of hashes with string values.
45
+ #
46
+ # @param [Array] result array of hashes, with object values.
47
+ # @return [Array] array of hashes, with string values.
28
48
  def self.stringify_values_of(result)
29
- # result is an array of hashes, but all the values are Nokogiri::XML::Attr objects, not strings.
30
- # We want them to be strings.
31
49
  result.collect! { |r| r.inject({}) {|h, (k, v)| h[k] = v.to_s; h } }
32
50
  end
33
51
  end
34
52
 
53
+ # Provides classes to wrap {http://www.followthemoney.org/index.phtml FollowTheMoney} data.
54
+ #
55
+ # For the details on the FollowTheMoney queries, see {http://www.followthemoney.org/services/methods.phtml the FollowTheMoney API documentation}.
35
56
  module FollowTheMoney
57
+
58
+ # Wrap {http://www.followthemoney.org/services/method_doc.phtml?a=11 Industry data}
36
59
  class Business < FollowTheMoneyResource
60
+
61
+ # Return a list of all business, industry, and sector categories. See the {http://www.followthemoney.org/services/method_doc.phtml?a=11 FollowTheMoney API}.
62
+ #
63
+ # @return [Business] A list of Business objects.
37
64
  def self.list
38
65
  next_page, result, page_num = "yes", [], 0
39
66
 
@@ -54,7 +81,14 @@ module GovKit
54
81
  end
55
82
  end
56
83
 
84
+ # Wrap contributions to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=32 FollowTheMoney API}.
57
85
  class Contribution < FollowTheMoneyResource
86
+
87
+ # Return contributions to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=32 FollowTheMoney API}.
88
+ #
89
+ # @param [Integer] nimsp_id the candidate id.
90
+ #
91
+ # @return [Contribution] a Contribution object, or array of Contribution objects, representing the contributions.
58
92
  def self.find(nimsp_id)
59
93
  next_page, result, page_num = "yes", [], 0
60
94
 
@@ -72,6 +106,11 @@ module GovKit
72
106
  parse(result)
73
107
  end
74
108
 
109
+ # Return a list of the top contributors to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=20 FollowTheMoney API}.
110
+ #
111
+ # @param [Integer] nimsp_id the candidate id.
112
+ #
113
+ # @return [[Contribution]] an array of Contribution objects.
75
114
  def self.top(nimsp_id)
76
115
  doc = get_xml("/candidates.top_contributor.php", :query => {"imsp_candidate_id" => nimsp_id})
77
116
  result = doc.search('//top_contributor').collect { |x| x.attributes }
@@ -81,7 +120,14 @@ module GovKit
81
120
  end
82
121
  end
83
122
 
123
+ # Wrap contributions by industry to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=24 FollowTheMoney API}.
124
+ #
84
125
  class IndustryContribution < Contribution
126
+ # Return contributions by industry.
127
+ #
128
+ # @param [Integer] nimsp_id the candidate id.
129
+ #
130
+ # @return [[Contribution]] an array of Contribution objects.
85
131
  def self.find(nimsp_id)
86
132
  doc = get_xml("/candidates.industries.php", :query => {"imsp_candidate_id" => nimsp_id})
87
133
  result = doc.search('//candidate_industry').collect { |x| x.attributes }
@@ -91,7 +137,14 @@ module GovKit
91
137
  end
92
138
  end
93
139
 
140
+ # Wrap contributions by sector to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=23 FollowTheMoney API}.
141
+ #
94
142
  class SectorContribution < Contribution
143
+ # Return conributions by sector.
144
+ #
145
+ # @param [Integer] nimsp_id the candidate id.
146
+ #
147
+ # @return [[Contribution]] an array of Contribution objects.
95
148
  def self.find(nimsp_id)
96
149
  doc = get_xml("/candidates.sectors.php", :query => {"imsp_candidate_id" => nimsp_id})
97
150
 
@@ -102,7 +155,14 @@ module GovKit
102
155
  end
103
156
  end
104
157
 
158
+ # Wrap contributions by business to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=25 FollowTheMoney API}.
159
+ #
105
160
  class BusinessContribution < Contribution
161
+ # Return contributions by business.
162
+ #
163
+ # @param [Integer] nimsp_id the candidate id.
164
+ #
165
+ # @return [[Contribution]] an array of Contribution objects.
106
166
  def self.find(nimsp_id)
107
167
  doc = get_xml("/candidates.businesses.php", :query => {"imsp_candidate_id" => nimsp_id})
108
168
 
@@ -4,14 +4,21 @@ require 'json'
4
4
  require 'CGI'
5
5
 
6
6
  module GovKit::OpenCongress
7
- autoload :Bill, 'gov_kit/open_congress/bill'
8
- autoload :BlogPost, 'gov_kit/open_congress/blog_post'
9
- autoload :NewsPost, 'gov_kit/open_congress/news_post'
10
- autoload :VotingComparison, 'gov_kit/open_congress/voting_comparison'
7
+ autoload :Bill, 'gov_kit/open_congress/bill'
8
+ autoload :BlogPost, 'gov_kit/open_congress/blog_post'
9
+ autoload :NewsPost, 'gov_kit/open_congress/news_post'
10
+ autoload :VotingComparison, 'gov_kit/open_congress/voting_comparison'
11
11
  autoload :RollCallComparison, 'gov_kit/open_congress/roll_call_comparison'
12
- autoload :Person, 'gov_kit/open_congress/person'
13
- autoload :PersonStat, 'gov_kit/open_congress/person_stat'
12
+ autoload :Person, 'gov_kit/open_congress/person'
13
+ autoload :PersonStat, 'gov_kit/open_congress/person_stat'
14
14
 
15
+ # Parent class for classes that wrap {http://www.opencongress.org/api OpenCongress data}.
16
+ #
17
+ # Unlike the wrapper classes for data from {FollowTheMoneyResource FollowTheMoney},
18
+ # {OpenStatesResource OpenStates}, {TransparencyDataResource TransparencyData},
19
+ # and {VoteSmartResource VoteSmart}, OpenCongressObject does not inherit
20
+ # from {GovKit::Resource}
21
+ #
15
22
  class OpenCongressObject
16
23
 
17
24
  def initialize(obj, params)
@@ -21,16 +28,19 @@ module GovKit::OpenCongress
21
28
  end
22
29
  end
23
30
 
31
+ # Create a query url, by adding the method path and query parameters to the
32
+ # base url of {http://www.opencongress.org/api}.
24
33
  def self.construct_url(api_method, params)
25
34
  url = nil
26
- if GovKit::configuration.opencongress_apikey == nil || GovKit::configuration.opencongress_apikey == ''
27
- raise "Failed to provide OpenCongress API Key"
28
- else
29
- url = "http://#{GovKit::configuration.opencongress_base_url}api/#{api_method}?key=#{GovKit::configuration.opencongress_apikey}#{hash2get(params)}&format=json"
30
- end
35
+ getkey = GovKit::configuration.opencongress_apikey.nil? ? "" : "&key=#{GovKit::configuration.opencongress_apikey}"
36
+ url = "http://#{GovKit::configuration.opencongress_base_url}api/#{api_method}?format=json#{hash2get(params)}#{getkey}"
31
37
  return url
32
38
  end
33
39
 
40
+ # Convert a hash to a string of query parameters.
41
+ #
42
+ # @param [Hash] h a hash.
43
+ # @return [String] a string of query parameters.
34
44
  def self.hash2get(h)
35
45
  get_string = ""
36
46
 
@@ -41,6 +51,17 @@ module GovKit::OpenCongress
41
51
  get_string
42
52
  end
43
53
 
54
+ # Iterates through the array returned by {make_call},
55
+ # converting each hash to an OpenCongressObject subclass.
56
+ #
57
+ # @param [Hash] results the array returned by make_call.
58
+ # @return a hash of arrays of OpenCongressObject objects, with these keys:
59
+ # * :also_supporting_bills
60
+ # * :also_opposing_bills
61
+ # * :also_disapproved_senators
62
+ # * :also_disapproved_representatives
63
+ # * :also_approved_senators
64
+ # * :also_approved_representatives
44
65
  def self.parse_supporting_results(result)
45
66
  working = result["opencongress_users_tracking"]
46
67
 
@@ -83,6 +104,12 @@ module GovKit::OpenCongress
83
104
 
84
105
  end
85
106
 
107
+ # Get the data from {http://www.opencongress.org/api OpenCongress data}. Called by subclasses.
108
+ #
109
+ # Parses the data using {http://flori.github.com/json/doc/index.html JSON.parse}, which
110
+ # returns an array of hashes.
111
+ #
112
+ # @return the returned data, as an array of hashes.
86
113
  def self.make_call(this_url)
87
114
  result = nil
88
115
  begin
@@ -95,4 +122,4 @@ module GovKit::OpenCongress
95
122
 
96
123
  end
97
124
  end
98
- end
125
+ end
@@ -1,29 +1,30 @@
1
1
  module GovKit
2
2
 
3
- # This is the parent class to the classes that wrap
3
+
4
+ # This is the parent class for the classes that wrap
4
5
  # the data returned to govkit.
5
6
  #
6
- # The subclasses are responsible for fetching the data as json from
7
- # different web services; Resource will then parse the json,
7
+ # Subclasses are responsible for fetching the data from
8
+ # different web services; Resource will then parse the returned data,
8
9
  # converting returned fields to instance methods.
9
10
  #
10
11
  # Initialize a Resource with a hash of attributes, or an array of hashes.
11
12
  # For each attribute, add a getter and setter to this instance.
12
- # So if
13
+ # @example
13
14
  # res = Resource.new { "aaa" => "111", "bbb" => "222", "ccc" => "333" }
14
- # then
15
15
  # res.aaa == "111"
16
16
  # res.bbb == "222"
17
17
  # res.ccc == "333"
18
18
  #
19
- # Includes HTTParty, which provides convenience methods like get().
20
- #
21
- # See http://rdoc.info/github/jnunemaker/httparty/master/HTTParty/ClassMethods
19
+ # Includes {http://rdoc.info/github/jnunemaker/httparty/master/HTTParty/ClassMethods HTTParty}, which provides convenience methods like get().
22
20
  class Resource
23
21
  include HTTParty
24
22
  format :json
25
23
 
24
+ # The attributes data returned by the service.
26
25
  attr_reader :attributes
26
+
27
+ # The response returned by the service.
27
28
  attr_reader :raw_response
28
29
 
29
30
  def initialize(attributes = {})
@@ -33,21 +34,22 @@ module GovKit
33
34
  unload(attributes)
34
35
  end
35
36
 
36
- # Returns a hash of the response object, potentially useful for comparison
37
- # on sync
37
+ # @return [Hash] the response object, potentially useful for comparison on sync
38
38
  #
39
39
  def to_md5
40
40
  Digest::MD5.hexdigest(@raw_response.body)
41
41
  end
42
42
 
43
- # Handles the basic responses we might get back from Net::HTTP.
44
- # On success, returns a new Resource based on the response.
43
+ # Handles the basic responses we might get back from a web service.
45
44
  #
46
45
  # On failure, throws an error.
47
46
  #
48
47
  # If a service returns something other than a 404 when an object is not found,
49
48
  # you'll need to handle that in the subclass.
50
49
  #
50
+ # @param [Object] response the object.
51
+ # @return [Resource] a new Resource created from the response.
52
+ #
51
53
  def self.parse(response)
52
54
 
53
55
  if response.class == HTTParty::Response
@@ -72,8 +74,8 @@ module GovKit
72
74
 
73
75
  # Instantiate new GovKit::Resources.
74
76
  #
75
- # +record+ is a hash of values returned by a service,
76
- # or an array of hashes.
77
+ # @param [Hash] record a hash of values returned by a service, or an array of hashes.
78
+ # @return [Resource]
77
79
  #
78
80
  # If +record+ is a hash, return a single GovKit::Resource.
79
81
  # If it is an array, return an array of GovKit::Resources.
@@ -86,16 +88,24 @@ module GovKit
86
88
  end
87
89
  end
88
90
 
91
+ # Instantiate a set of records.
92
+ #
93
+ # @return [Array] Array of records
94
+ # @param [Array] collection An array of records
89
95
  def self.instantiate_collection(collection)
90
96
  collection.collect! { |record| new(record) }
91
97
  end
92
98
 
93
- # Given a hash of attributes, assign it to the @attributes member,
94
- # then for each attribute, create or set a pair of member accessors with the name
99
+ # Given a hash of attributes, assign it to the @attributes member.
100
+ # Then for each attribute, create or set a pair of member accessors with the name
95
101
  # of the attribute's key.
102
+ #
96
103
  # If the value of the attribute is itself an array or a hash,
97
104
  # then create a new class with the (singularized) key as a name, and with a parent class of Resource,
98
105
  # and initialize it with the hash.
106
+ #
107
+ # @param [Hash] attributes the attributes returned by the web service.
108
+ #
99
109
  def unload(attributes)
100
110
  raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
101
111