guidestar-ruby 1.0.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.
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