govkit-h 0.7.1.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 (72) hide show
  1. data/.document +5 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +20 -0
  5. data/README.md +70 -0
  6. data/Rakefile +82 -0
  7. data/USAGE +1 -0
  8. data/VERSION +1 -0
  9. data/generators/govkit/govkit_generator.rb +24 -0
  10. data/generators/govkit/templates/govkit.rb +24 -0
  11. data/govkit.gemspec +130 -0
  12. data/init.rb +4 -0
  13. data/lib/generators/govkit/govkit_generator.rb +21 -0
  14. data/lib/generators/govkit/templates/create_mentions.rb +21 -0
  15. data/lib/generators/govkit/templates/govkit.rb +24 -0
  16. data/lib/generators/govkit/templates/mention.rb +15 -0
  17. data/lib/gov_kit.rb +45 -0
  18. data/lib/gov_kit/acts_as_noteworthy.rb +63 -0
  19. data/lib/gov_kit/configuration.rb +58 -0
  20. data/lib/gov_kit/follow_the_money.rb +176 -0
  21. data/lib/gov_kit/open_congress.rb +125 -0
  22. data/lib/gov_kit/open_congress/bill.rb +171 -0
  23. data/lib/gov_kit/open_congress/blog_post.rb +15 -0
  24. data/lib/gov_kit/open_congress/news_post.rb +15 -0
  25. data/lib/gov_kit/open_congress/person.rb +141 -0
  26. data/lib/gov_kit/open_congress/person_stat.rb +13 -0
  27. data/lib/gov_kit/open_congress/roll_call.rb +14 -0
  28. data/lib/gov_kit/open_congress/roll_call_comparison.rb +28 -0
  29. data/lib/gov_kit/open_congress/voting_comparison.rb +44 -0
  30. data/lib/gov_kit/open_states.rb +132 -0
  31. data/lib/gov_kit/railtie.rb +24 -0
  32. data/lib/gov_kit/resource.rb +190 -0
  33. data/lib/gov_kit/search_engines.rb +7 -0
  34. data/lib/gov_kit/search_engines/bing.rb +38 -0
  35. data/lib/gov_kit/search_engines/google_blog.rb +32 -0
  36. data/lib/gov_kit/search_engines/google_news.rb +47 -0
  37. data/lib/gov_kit/search_engines/technorati.rb +35 -0
  38. data/lib/gov_kit/search_engines/wikipedia.rb +27 -0
  39. data/lib/gov_kit/transparency_data.rb +144 -0
  40. data/lib/gov_kit/vote_smart.rb +126 -0
  41. data/lib/govkit.rb +1 -0
  42. data/spec/fixtures/bing/news_search.response +1 -0
  43. data/spec/fixtures/bing/no_results.response +1 -0
  44. data/spec/fixtures/follow_the_money/business-page0.response +28 -0
  45. data/spec/fixtures/follow_the_money/business-page1.response +12 -0
  46. data/spec/fixtures/follow_the_money/contribution.response +12 -0
  47. data/spec/fixtures/follow_the_money/unauthorized.response +8 -0
  48. data/spec/fixtures/open_congress/person.response +8 -0
  49. data/spec/fixtures/open_states/401.response +10 -0
  50. data/spec/fixtures/open_states/404.response +9 -0
  51. data/spec/fixtures/open_states/410.response +6 -0
  52. data/spec/fixtures/open_states/bill.response +240 -0
  53. data/spec/fixtures/open_states/bill_query.response +1990 -0
  54. data/spec/fixtures/open_states/committee_find.response +53 -0
  55. data/spec/fixtures/open_states/committee_query.response +190 -0
  56. data/spec/fixtures/open_states/legislator.response +34 -0
  57. data/spec/fixtures/open_states/legislator_query.response +144 -0
  58. data/spec/fixtures/open_states/state.response +60 -0
  59. data/spec/fixtures/search_engines/google_news.response +8 -0
  60. data/spec/fixtures/transparency_data/contributions.response +18 -0
  61. data/spec/fixtures/transparency_data/entities_search.response +7 -0
  62. data/spec/fixtures/transparency_data/entities_search_limit_0.response +7 -0
  63. data/spec/fixtures/transparency_data/entities_search_limit_1.response +7 -0
  64. data/spec/fixtures/transparency_data/grants_find_all.response +7 -0
  65. data/spec/fixtures/transparency_data/lobbyists_find_all.response +7 -0
  66. data/spec/follow_the_money_spec.rb +61 -0
  67. data/spec/open_congress_spec.rb +108 -0
  68. data/spec/open_states_spec.rb +213 -0
  69. data/spec/search_engines_spec.rb +44 -0
  70. data/spec/spec_helper.rb +36 -0
  71. data/spec/transparency_data_spec.rb +106 -0
  72. metadata +258 -0
@@ -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
@@ -0,0 +1,45 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require 'digest/md5'
4
+ require 'active_support'
5
+ require 'nokogiri'
6
+ require 'iconv'
7
+ require 'httparty'
8
+ require 'open-uri'
9
+ require 'json'
10
+ require 'gov_kit/configuration'
11
+ require 'csv'
12
+
13
+ if RUBY_VERSION[0,3] == "1.8"
14
+ require 'fastercsv'
15
+ end
16
+
17
+ module GovKit
18
+ autoload :Resource, 'gov_kit/resource'
19
+ autoload :OpenStates, 'gov_kit/open_states'
20
+ autoload :TransparencyData, 'gov_kit/transparency_data'
21
+ autoload :VoteSmart, 'gov_kit/vote_smart'
22
+ autoload :ActsAsNoteworthy, 'gov_kit/acts_as_noteworthy'
23
+ autoload :FollowTheMoney, 'gov_kit/follow_the_money'
24
+ autoload :OpenCongress, 'gov_kit/open_congress'
25
+ autoload :SearchEngines, 'gov_kit/search_engines'
26
+
27
+ # Convenience class to represent a news story or blog post.
28
+ # Used by GovKit::SearchEngines classes.
29
+ class Mention
30
+ attr_accessor :url, :excerpt, :title, :source, :date, :weight, :search_source
31
+ end
32
+
33
+ class GovKitError < StandardError
34
+ end
35
+
36
+ class NotAuthorized < GovKitError; end
37
+
38
+ class InvalidRequest < GovKitError; end
39
+
40
+ class ResourceNotFound < GovKitError; end
41
+
42
+ class ServerError < GovKitError; end
43
+
44
+ class ClientError < GovKitError; end
45
+ end
@@ -0,0 +1,63 @@
1
+ module GovKit::ActsAsNoteworthy
2
+
3
+ def self.included(base)
4
+ base.extend ActMethods
5
+ end
6
+
7
+ # Module to make a rails model act as a noteworthy object, linking it to govkit's mention model
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
12
+ def acts_as_noteworthy(options={})
13
+ class_inheritable_accessor :options
14
+ self.options = options
15
+
16
+ unless included_modules.include? InstanceMethods
17
+ instance_eval do
18
+ has_many :mentions, :as => :owner, :order => 'date desc'
19
+
20
+ with_options :as => :owner, :class_name => "Mention" do |c|
21
+ c.has_many :google_news_mentions, :conditions => {:search_source => "Google News"}, :order => 'date desc'
22
+ c.has_many :google_blog_mentions, :conditions => {:search_source => "Google Blogs"}, :order => 'date desc'
23
+ # c.has_many :technorati_mentions, :conditions => {:search_source => "Technorati"}, :order => 'date desc'
24
+ c.has_many :bing_mentions, :conditions => {:search_source => "Bing"}, :order => 'date desc'
25
+ end
26
+ end
27
+
28
+ extend ClassMethods
29
+ include InstanceMethods
30
+ end
31
+ end
32
+ end
33
+
34
+ module ClassMethods
35
+ end
36
+
37
+ # A module that adds methods to individual instances of the noteworthy class.
38
+ module InstanceMethods
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.
42
+ def raw_mentions
43
+ opts = self.options.clone
44
+ attributes = opts.delete(:with)
45
+
46
+ if opts[:geo]
47
+ opts[:geo] = self.instance_eval("#{opts[:geo]}")
48
+ end
49
+
50
+ query = []
51
+ attributes.each do |attr|
52
+ query << self.instance_eval("#{attr}")
53
+ end
54
+
55
+ {
56
+ :google_news => GovKit::SearchEngines::GoogleNews.search(query, opts),
57
+ :google_blogs => GovKit::SearchEngines::GoogleBlog.search(query, opts),
58
+ # :technorati => GovKit::SearchEngines::Technorati.search(query),
59
+ :bing => GovKit::SearchEngines::Bing.search(query, opts)
60
+ }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,58 @@
1
+ module GovKit
2
+ class Configuration
3
+ attr_accessor :sunlight_apikey, :openstates_base_url, :transparency_data_base_url, :transparency_data_categories_url
4
+ attr_accessor :votesmart_apikey, :votesmart_base_url
5
+ attr_accessor :openstates_apikey, :ftm_apikey, :ftm_base_url
6
+ attr_accessor :opencongress_apikey, :opencongress_base_url
7
+ attr_accessor :technorati_apikey, :technorati_base_url
8
+ attr_accessor :google_blog_base_url, :google_news_base_url
9
+ attr_accessor :wikipedia_base_url
10
+ attr_accessor :bing_appid, :bing_base_url
11
+
12
+ def initialize
13
+ @sunlight_apikey = @openstates_apikey = @votesmart_apikey = @ftm_apikey = ''
14
+ @openstates_base_url = 'openstates.sunlightlabs.com/api/v1/'
15
+ @transparency_data_base_url = 'transparencydata.com/api/1.0/'
16
+ @votesmart_base_url = 'api.votesmart.org/'
17
+ @ftm_base_url = 'api.followthemoney.org/'
18
+ @opencongress_base_url = 'www.opencongress.org/'
19
+ @technorati_base_url = 'api.technorati.com'
20
+ @bing_base_url = 'api.search.live.net'
21
+ @google_blog_base_url = 'blogsearch.google.com'
22
+ @google_news_base_url = 'news.google.com'
23
+ @wikipedia_base_url = 'en.wikipedia.org'
24
+
25
+ # Permant home for contribution category mappings
26
+ @transparency_data_categories_url = 'http://assets.transparencydata.org.s3.amazonaws.com/docs/catcodes.csv'
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
38
+ end
39
+
40
+ class << self
41
+ attr_accessor :configuration
42
+
43
+ def configuration
44
+ @configuration = Configuration.new if @configuration.nil?
45
+ @configuration
46
+ end
47
+ end
48
+
49
+ # Configure GovKit in config/initializers/govkit.rb
50
+ #
51
+ # @example
52
+ # GovKit.configure do |config|
53
+ # config.sunlight_apikey = ''
54
+ # end
55
+ def self.configure
56
+ yield(configuration)
57
+ end
58
+ end
@@ -0,0 +1,176 @@
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}.
8
+ class FollowTheMoneyResource < Resource
9
+ default_params :key => GovKit::configuration.ftm_apikey
10
+ base_uri GovKit::configuration.ftm_base_url
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
+ #
21
+ def self.get_xml(path, options)
22
+ doc = Nokogiri::XML(get(path, options))
23
+
24
+ e = doc.search("//error")
25
+
26
+ # Deal with whatever error comes back
27
+ if e.size > 0
28
+ raise case e.first.attributes['code'].value
29
+ when "100"
30
+ GovKit::NotAuthorized
31
+ when "300"
32
+ GovKit::InvalidRequest
33
+ when "200"
34
+ GovKit::ResourceNotFound
35
+ else
36
+ GovKit::InvalidRequest
37
+ end, e.first.attributes['text'].value
38
+ end
39
+
40
+ doc
41
+ end
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.
48
+ def self.stringify_values_of(result)
49
+ result.collect! { |r| r.inject({}) {|h, (k, v)| h[k] = v.to_s; h } }
50
+ end
51
+ end
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}.
56
+ module FollowTheMoney
57
+
58
+ # Wrap {http://www.followthemoney.org/services/method_doc.phtml?a=11 Industry data}
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.
64
+ def self.list
65
+ next_page, result, page_num = "yes", [], 0
66
+
67
+ until next_page != "yes"
68
+ # puts "Getting batch number #{page_num}"
69
+
70
+ doc = get_xml("/base_level.industries.list.php", :query => {:page => page_num})
71
+
72
+ next_page = doc.children.first.attributes['next_page'].value
73
+
74
+ page_num += 1
75
+
76
+ result += doc.search('//business_detail').collect { |x| x.attributes }
77
+ end
78
+
79
+ stringify_values_of(result)
80
+ parse(result)
81
+ end
82
+ end
83
+
84
+ # Wrap contributions to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=32 FollowTheMoney API}.
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.
92
+ def self.find(nimsp_id)
93
+ next_page, result, page_num = "yes", [], 0
94
+
95
+ until next_page != "yes"
96
+ doc = get_xml("/candidates.contributions.php", :query => {"imsp_candidate_id" => nimsp_id, :page => page_num})
97
+
98
+ next_page = doc.children.first.attributes['next_page'].value
99
+
100
+ page_num += 1
101
+
102
+ result += doc.search('//contribution').collect { |x| x.attributes }
103
+ end
104
+
105
+ stringify_values_of(result)
106
+ parse(result)
107
+ end
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.
114
+ def self.top(nimsp_id)
115
+ doc = get_xml("/candidates.top_contributor.php", :query => {"imsp_candidate_id" => nimsp_id})
116
+ result = doc.search('//top_contributor').collect { |x| x.attributes }
117
+
118
+ stringify_values_of(result)
119
+ parse(result)
120
+ end
121
+ end
122
+
123
+ # Wrap contributions by industry to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=24 FollowTheMoney API}.
124
+ #
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.
131
+ def self.find(nimsp_id)
132
+ doc = get_xml("/candidates.industries.php", :query => {"imsp_candidate_id" => nimsp_id})
133
+ result = doc.search('//candidate_industry').collect { |x| x.attributes }
134
+
135
+ stringify_values_of(result)
136
+ parse(result)
137
+ end
138
+ end
139
+
140
+ # Wrap contributions by sector to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=23 FollowTheMoney API}.
141
+ #
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.
148
+ def self.find(nimsp_id)
149
+ doc = get_xml("/candidates.sectors.php", :query => {"imsp_candidate_id" => nimsp_id})
150
+
151
+ result = doc.search('//candidate_sector').collect { |x| x.attributes }
152
+
153
+ stringify_values_of(result)
154
+ parse(result)
155
+ end
156
+ end
157
+
158
+ # Wrap contributions by business to a candidate. See the {http://www.followthemoney.org/services/method_doc.phtml?a=25 FollowTheMoney API}.
159
+ #
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.
166
+ def self.find(nimsp_id)
167
+ doc = get_xml("/candidates.businesses.php", :query => {"imsp_candidate_id" => nimsp_id})
168
+
169
+ result = doc.search('//candidate_business').collect { |x| x.attributes }
170
+
171
+ stringify_values_of(result)
172
+ parse(result)
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,125 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'json'
4
+ require 'CGI'
5
+
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'
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'
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
+ #
22
+ class OpenCongressObject
23
+
24
+ def initialize(obj, params)
25
+ params.each do |key, value|
26
+ key = key.to_sym if RUBY_VERSION[0,3] == "1.9"
27
+ instance_variable_set("@#{key}", value) if obj.instance_methods.include? key
28
+ end
29
+ end
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}.
33
+ def self.construct_url(api_method, params)
34
+ url = nil
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}"
37
+ return url
38
+ end
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.
44
+ def self.hash2get(h)
45
+ get_string = ""
46
+
47
+ h.each_pair do |key, value|
48
+ get_string += "&#{key.to_s}=#{CGI::escape(value.to_s)}"
49
+ end
50
+
51
+ get_string
52
+ end
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
65
+ def self.parse_supporting_results(result)
66
+ working = result["opencongress_users_tracking"]
67
+
68
+ also_supporting_bills = []
69
+ working["also_supporting_bills"]["bill"].each do |bill|
70
+ also_supporting_bills << Bill.new(bill)
71
+ end
72
+
73
+ also_opposing_bills = []
74
+ working["also_opposing_bills"]["bill"].each do |bill|
75
+ also_opposing_bills << Bill.new(bill)
76
+ end
77
+
78
+ also_disapproved_senators = []
79
+ working["also_disapproved_senators"]["person"].each do |person|
80
+ also_disapproved_senators << Person.new(person)
81
+ end
82
+
83
+ also_disapproved_representatives = []
84
+ working["also_disapproved_representatives"]["person"].each do |person|
85
+ also_disapproved_representatives << Person.new(person)
86
+ end
87
+
88
+ also_approved_senators = []
89
+ working["also_approved_senators"]["person"].each do |person|
90
+ also_approved_senators << Person.new(person)
91
+ end
92
+
93
+ also_approved_representatives = []
94
+ working["also_approved_representatives"]["person"].each do |person|
95
+ also_approved_representatives << Person.new(person)
96
+ end
97
+
98
+ return {:also_supporting_bills => also_supporting_bills,
99
+ :also_opposing_bills => also_opposing_bills,
100
+ :also_disapproved_senators => also_disapproved_senators,
101
+ :also_disapproved_representatives => also_disapproved_representatives,
102
+ :also_approved_senators => also_approved_senators,
103
+ :also_approved_representatives => also_approved_representatives}
104
+
105
+ end
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.
113
+ def self.make_call(this_url)
114
+ result = nil
115
+ begin
116
+ result = JSON.parse(open(this_url).read)
117
+ rescue => e
118
+ puts e
119
+ end
120
+
121
+ return result
122
+
123
+ end
124
+ end
125
+ end