guidestar-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ *.log
3
+ pkg/*
4
+ coverage/*
5
+ doc/*
6
+ benchmarks/*
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ guidestar-ruby (1.0.0)
5
+ nokogiri (~> 1.4.3.1)
6
+ rest-client (~> 1.6.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ mime-types (1.18)
12
+ nokogiri (1.4.3.1)
13
+ rest-client (1.6.7)
14
+ mime-types (>= 1.16)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ guidestar-ruby!
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Gemini SBS, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # Guidestar
2
+
3
+ Ruby wrapper around the [Guidestar](http://guidestar.org) API.
4
+
5
+ ## Install
6
+
7
+ gem install guidestar-ruby
8
+
9
+ ## Usage
10
+
11
+ First initialize the client with your credentials:
12
+
13
+ ```ruby
14
+ Guidestar::Client.set_credentials(<user>, <password>)
15
+ ```
16
+
17
+ Now you can perform searches by keyword:
18
+
19
+ ```ruby
20
+ Guidestar::Client.search(:keyword => "poverty")
21
+ ```
22
+
23
+ Search by organization name:
24
+
25
+ ```ruby
26
+ Guidestar::Client.search(:name=> "Red Cross")
27
+ ```
28
+
29
+ Search by EIN:
30
+
31
+ ```ruby
32
+ Guidestar::Client.search(:ein => "52-5367724")
33
+ ```
34
+
35
+ Search by city and state:
36
+
37
+ ```ruby
38
+ Guidestar::Client.search(:city => "San Francisco", :state => "CA")
39
+ ```
40
+
41
+ Search by zip:
42
+
43
+ ```ruby
44
+ Guidestar::Client.search(:zip => "23556")
45
+ ```
46
+
47
+ Search by NTEE code:
48
+
49
+ ```ruby
50
+ Guidestar::Client.search(:ntee_code => "A25")
51
+ ```
52
+
53
+ Additional options (and their respective defaults):
54
+
55
+ ```ruby
56
+ {
57
+ :page_size => 25, # number of results per page
58
+ :offset => 0, # page number
59
+ :categories => ["C1_Arts_Culture_and_Humanities"],
60
+ :sub_categories => ["C1_Performing_Arts"]
61
+ }
62
+ ```
63
+
64
+ ### Organization Categories & Sub-Categories
65
+
66
+ Categories (defaults to "C1_Arts_Culture_and_Humanities"):
67
+
68
+ * "C1_Arts_Culture_and_Humanities"
69
+ * "C2_Education_and_Research"
70
+ * "C3_Environment_and_Animals"
71
+ * "C4_Health"
72
+ * "C5_Human_Services"
73
+ * "C6_International"
74
+ * "C7_Public_Societal_Benefit"
75
+ * "C8_Religion"
76
+ * "C9_Unknown"
77
+
78
+ Sub-Categories (defaults to "C4_Performing_Arts"):
79
+
80
+ * "C1_Humanities_and_Historical_Societies"
81
+ * "C1_Media"
82
+ * "C1_Museums"
83
+ * "C1_Performing_Arts"
84
+ * "C1_Service_and_Other"
85
+ * "C2_College_and_University"
86
+ * "C2_Elementary_and_Secondary"
87
+ * "C2_Libraries"
88
+ * "C2_Research_Institutes"
89
+ * "C2_Service_and_Other"
90
+ * "C2_Vocational_Technical_and_Adult"
91
+ * "C3_Animal_Protection_Welfare_and_Services"
92
+ * "C3_Beautification_and_Horticulture"
93
+ * "C3_Conservation_and_Environmental_Education"
94
+ * "C3_Health_Care_Facilities_and_Programs"
95
+ * "C3_Pollution"
96
+ * "C3_Service_and_Other"
97
+ * "C3_Zoos_and_Veterinary_Services"
98
+ * "C4_Addiction_and_Substance_Abuse"
99
+ * "C4_Diseases_and_Disease_Research"
100
+ * "C4_Health_Care_Facilities_and_Programs"
101
+ * "C4_Medical_Disciplines_and_Specialty_Research"
102
+ * "C4_Mental_Health_and_Crisis_Services"
103
+ * "C5_Agriculture_Food_and_Nutrition"
104
+ * "C5_Crime_and_Legal_Related"
105
+ * "C5_Employment_and_Occupations"
106
+ * "C5_General_Human_Services"
107
+ * "C5_Housing"
108
+ * "C5_Public_Safety_Disaster_Preparedness_and_Relief"
109
+ * "C5_Recreation_and_Sports"
110
+ * "C5_Youth_Development"
111
+ * "C6_International_Development_and_Relief_Services"
112
+ * "C6_International_Human_Rights"
113
+ * "C6_International_Peace_and_Security"
114
+ * "C6_Promotion_of_International_Understanding"
115
+ * "C6_Service_and_Other"
116
+ * "C7_Civil_Rights_and_Liberties"
117
+ * "C7_Community_Improvement"
118
+ * "C7_Mutual_or_Membership_Benefit_Organizations"
119
+ * "C7_Philanthropy_Voluntarism_and_Public_Benefit"
120
+ * "C7_Service_and_Other"
121
+ * "C7_Voter_Education_and_Registration"
122
+ * "C8_Buddhist"
123
+ * "C8_Christian"
124
+ * "C8_Hindu"
125
+ * "C8_Islamic"
126
+ * "C8_Jewish"
127
+ * "C8_Religious_Media"
128
+ * "C8_Service_and_Other"
129
+ * "C9_Unknown"
130
+
131
+ ## Dependencies
132
+
133
+ * [nokogiri](http://github.com/tenderlove/nokogiri)
134
+ * [rest-client](http://github.com/archiloque/rest-client)
135
+
136
+ ## Copyright
137
+
138
+ Copyright (c) 2012 Gemini SBS. See LICENSE for details.
139
+
140
+ ## Authors
141
+
142
+ * [Mauricio Gomes](http://github.com/mgomes)
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require 'rspec/core'
6
+ require 'rspec/core/rake_task'
7
+
8
+ RSpec::Core::RakeTask.new(:spec) do |spec|
9
+ spec.pattern = FileList['spec/**/*_spec.rb']
10
+ end
11
+
12
+ task :default => :spec
13
+
14
+ require 'rake/rdoctask'
15
+ Rake::RDocTask.new do |rdoc|
16
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
17
+
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = "test #{version}"
20
+ rdoc.rdoc_files.include('README*')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = %q{guidestar-ruby}
6
+ s.summary = %q{A ruby wrapper around the Guidestar API}
7
+ s.description = %q{A ruby wrapper around the Guidestar API}
8
+ s.homepage = %q{http://github.com/geminisbs/guidestar-ruby}
9
+ s.version = File.read(File.join(File.dirname(__FILE__), 'VERSION'))
10
+ s.authors = ["Mauricio Gomes"]
11
+ s.email = "mgomes@geminisbs.com"
12
+
13
+ s.add_dependency "nokogiri", "~> 1.4.3.1"
14
+ s.add_dependency "rest-client", "~> 1.6.0"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,21 @@
1
+ require 'uri'
2
+ require 'nokogiri'
3
+ require 'rest_client'
4
+
5
+ require 'guidestar/connection'
6
+ require 'guidestar/client'
7
+
8
+ module Guidestar
9
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
10
+ ENDPOINT = "https://gsservices.guidestar.org/GuideStar_SearchService/SearchService.asmx/GuideStarDetail"
11
+
12
+ class GuidestarError < StandardError; end
13
+ class InsufficientArgs < GuidestarError; end
14
+ class Unauthorized < GuidestarError; end
15
+ class NotFound < GuidestarError; end
16
+ class ServerError < GuidestarError; end
17
+ class Unavailable < GuidestarError; end
18
+ class Timeout < GuidestarError; end
19
+ class DecodeError < GuidestarError; end
20
+ class CredentialsNotSpecified < GuidestarError; end
21
+ end
data/lib/guidestar.rb ADDED
@@ -0,0 +1,2 @@
1
+ # So you can require "guidestar" instead of "guidestar-ruby"
2
+ require "guidestar-ruby"
@@ -0,0 +1,65 @@
1
+ module Guidestar
2
+
3
+ class Client
4
+
5
+ @@default_options = { :version => "1.0", :pageSize => 25, :offset => 0 }
6
+ @@options_mapping = { :name => :orgName,
7
+ :zip_radius => :zipradius,
8
+ :ntee_code => :nteeCode,
9
+ :page_size => :pageSize
10
+ }
11
+
12
+ @@connection = nil
13
+
14
+ class << self
15
+
16
+ def set_credentials(username, password, proxy=nil)
17
+ @@connection = Connection.new(username, password, proxy)
18
+ end
19
+
20
+ def search(*args)
21
+ options = extract_options!(args)
22
+ options = translate_options(options)
23
+ result = post(@@default_options.merge(options))
24
+ end
25
+
26
+ private
27
+
28
+ def post(data)
29
+ raise CredentialsNotSpecified if @@connection.nil?
30
+ @@connection.post data
31
+ end
32
+
33
+ def decode_host(realm)
34
+ realm.split('/').delete_if {|i| i == 'index.html' }.join('/').gsub(':5058', '')
35
+ end
36
+
37
+ def extract_options!(args)
38
+ if args.last.is_a?(Hash)
39
+ return args.pop
40
+ else
41
+ return {}
42
+ end
43
+ end
44
+
45
+ def translate_options(options)
46
+ dup_options = {}
47
+ options.each_pair do |k,v|
48
+ if @@options_mapping[k]
49
+ dup_options[@@options_mapping[k]] = v
50
+ else
51
+ dup_options[k] = v
52
+ end
53
+ end
54
+
55
+ # Ensure EINs are in the format NN-NNNNNNN
56
+ dup_options[:ein].insert(2, '-') if dup_options[:ein] && dup_options[:ein][2] != '-'
57
+
58
+ dup_options
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,138 @@
1
+ module Guidestar
2
+
3
+ class Connection
4
+
5
+ attr_reader :username, :password
6
+
7
+ def initialize(username, password, proxy=nil)
8
+ @username = username
9
+ @password = password
10
+ @proxy = proxy
11
+ end
12
+
13
+ def post(data)
14
+ request :post, data
15
+ end
16
+
17
+ private
18
+
19
+ def request(method, data)
20
+ response = send_request(method, construct_document(data))
21
+
22
+ deconstruct_document response
23
+ end
24
+
25
+ def send_request(method, data)
26
+ RestClient.proxy = @proxy unless @proxy.nil?
27
+
28
+ begin
29
+ response = RestClient.post(ENDPOINT, :xmlInput => data, :multipart => false)
30
+ rescue => e
31
+ raise_errors(e.response)
32
+ end
33
+
34
+ response
35
+ end
36
+
37
+ def construct_document(data)
38
+ builder = Nokogiri::XML::Builder.new do |xml|
39
+ xml.query {
40
+ xml.version data[:version]
41
+ xml.login @username
42
+ xml.password @password
43
+ xml.pageSize data[:pageSize]
44
+ xml.offset data[:offset]
45
+ xml.orgName data[:orgName] if data[:orgName]
46
+ xml.ein data[:ein] if data[:ein]
47
+ xml.city data[:city] if data[:city]
48
+ xml.state data[:state] if data[:state]
49
+ xml.zip data[:zip] if data[:zip]
50
+ xml.nteeCode data[:nteeCode] if data[:nteeCode]
51
+ if data[:categories] && data[:categories].is_a?(Array)
52
+ data[:categories].each {|category| xml.category category }
53
+ end
54
+
55
+ if data[:sub_categories] && data[:sub_categories].is_a?(Array)
56
+ data[:sub_categories].each {|sub_category| xml.subCategory sub_category }
57
+ end
58
+ }
59
+ end
60
+
61
+ builder.to_xml
62
+ end
63
+
64
+ def deconstruct_document(response)
65
+ organizations = []
66
+ raise(Timeout, "The Guidestar server could not be reached") if response.nil?
67
+
68
+ begin
69
+ doc = Nokogiri::XML.parse(CGI.unescapeHTML(response.body))
70
+ doc.remove_namespaces!
71
+ doc.xpath('//organizations/organization').each do |org|
72
+ organization = {}
73
+ org.xpath('.//generalInformation').each do |info|
74
+ organization[:name] = info.at('orgName').text.strip
75
+ organization[:ein] = info.at('ein').text.gsub('-', '')
76
+ organization[:website] = info.at('url').text
77
+ organization[:ruling_date] = info.at('rulingYear').text
78
+ organization[:asset_amount] = info.at('assets').text ? info.at('assets').text.to_i : nil
79
+ organization[:annual_revenue] = info.at('income').text ? info.at('income').text.to_i : nil
80
+ organization[:alternate_name] = info.at('aka').text
81
+
82
+ info.xpath('.//address').each do |address|
83
+ organization[:address] = address.at('addressLine1').text
84
+ organization[:address2] = address.at('addressLine2').text
85
+ organization[:city] = address.at('city').text
86
+ organization[:state] = address.at('state').text
87
+ organization[:zip] = address.at('zip').text
88
+ end
89
+
90
+ info.xpath('.//contact').each do |contact|
91
+ organization[:contact_name] = [contact.at('firstName').text, contact.at('lastName').text].join(' ')
92
+ organization[:email] = contact.at('email').text
93
+ organization[:phone] = contact.at('phone').text
94
+ organization[:fax] = contact.at('fax').text
95
+ end
96
+
97
+ organization[:non_profit] = true
98
+
99
+ organization[:ntees] = []
100
+ info.xpath('.//ntees/ntee').each do |ntee|
101
+ next if ntee.at('code').text == ""
102
+ organization[:ntees] << { :code => ntee.at('code').text, :description => ntee.at('description').text }
103
+ end
104
+
105
+ end
106
+
107
+ organizations << tidy_org(organization)
108
+ end
109
+ rescue
110
+ raise DecodeError, "content: <#{response.body}>"
111
+ end
112
+
113
+ organizations
114
+ end
115
+
116
+ def tidy_org(organization)
117
+ organization.each_pair do |k, v|
118
+ organization[k].strip! if v.class == String
119
+ end
120
+ organization
121
+ end
122
+
123
+ def raise_errors(response)
124
+ raise(Timeout, "The Guidestar server could not be reached") if response.nil?
125
+
126
+ case response.code
127
+ when 500
128
+ raise ServerError, "Guidestar server had an internal error. #{response.description}\n\n#{response.body}"
129
+ when 502..503
130
+ raise Unavailable, response.description
131
+ else
132
+ raise SemaphoreError, response.description
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Guidstar" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format nested
3
+ --loadby mtime
4
+ --backtrace
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'guidestar'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guidestar-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mauricio Gomes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-03 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &70299699930800 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.3.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70299699930800
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70299699930260 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.6.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70299699930260
36
+ description: A ruby wrapper around the Guidestar API
37
+ email: mgomes@geminisbs.com
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - .gitignore
43
+ - Gemfile
44
+ - Gemfile.lock
45
+ - LICENSE
46
+ - README.md
47
+ - Rakefile
48
+ - VERSION
49
+ - guidestar-ruby.gemspec
50
+ - lib/guidestar-ruby.rb
51
+ - lib/guidestar.rb
52
+ - lib/guidestar/client.rb
53
+ - lib/guidestar/connection.rb
54
+ - spec/guidestar-ruby.rb
55
+ - spec/spec.opts
56
+ - spec/spec_helper.rb
57
+ homepage: http://github.com/geminisbs/guidestar-ruby
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.16
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: A ruby wrapper around the Guidestar API
81
+ test_files:
82
+ - spec/guidestar-ruby.rb
83
+ - spec/spec.opts
84
+ - spec/spec_helper.rb