guidestar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Kelly Martin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Guidestar
2
+
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ gem 'guidestar'
9
+
10
+ Or install it yourself as:
11
+
12
+ $ gem install guidestar
13
+
14
+ Then configure it with an initializer like `/config/initializers/guidestar.rb`:
15
+
16
+ Guidestar.configure do |config|
17
+ config.username = 'john@guidestar.org'
18
+ config.password = 'l3tm31n'
19
+ end
20
+
21
+ ## Usage
22
+
23
+ Once you initialize it, you can use it in your code via:
24
+
25
+ client = Guidestar::Client.new
26
+ results = client.search(:keyword => 'monkeys', :limit => 20)
27
+
28
+ results.xml
29
+ # => raw xml data
30
+
31
+ results.search_time
32
+ # => 0.12
33
+ results.total_count
34
+ # => 1292
35
+
36
+ results.organizations.each do |org|
37
+ org.name
38
+ # => 'Monkey Paradise'
39
+ org.ein
40
+ # => '23-5553434'
41
+ org.ein.to_i # with some magic
42
+ # => 235553434
43
+ org.tax_deductible?
44
+ # true
45
+ end
46
+
47
+ For getting the next page of results, it behaves similarly to kaminari or will_paginate:
48
+
49
+ results.per(50).page(2).organizations
50
+
51
+
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/guidestar.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/guidestar/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Kelly Martin']
6
+ gem.email = ['kellymartinv@gmail.com']
7
+ gem.description = "Allows access to the Guidestar API"
8
+ gem.summary = "Use this gem to access the Guidestar API"
9
+ gem.homepage = 'http://github.com/kellym/guidestar'
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = 'guidestar'
15
+ gem.require_paths = ['lib']
16
+ gem.version = Guidestar::VERSION
17
+
18
+ gem.add_dependency 'faraday', '~> 0.8'
19
+ gem.add_dependency 'faraday_middleware', '~> 0.9'
20
+ gem.add_dependency 'rash', '~> 0.3'
21
+ gem.add_dependency 'multi_xml', '~> 0.5'
22
+ gem.add_dependency 'nokogiri', '~> 1.5'
23
+ end
@@ -0,0 +1,38 @@
1
+ require 'faraday'
2
+
3
+ # @api private
4
+ module Faraday
5
+ class Response::RaiseGuidestarError < Response::Middleware
6
+ def on_complete(response)
7
+ case response[:status].to_i
8
+ when 303
9
+ raise Guidestar::SeeOther, error_message(response)
10
+ when 400
11
+ raise Guidestar::BadRequest, error_message(response)
12
+ when 401
13
+ raise Guidestar::Unauthorized, error_message(response)
14
+ when 403
15
+ raise Guidestar::Forbidden, error_message(response)
16
+ when 404
17
+ raise Guidestar::NotFound, error_message(response)
18
+ when 406
19
+ raise Guidestar::NotAcceptable, error_message(response)
20
+ when 422
21
+ raise Guidestar::UnprocessableEntity, error_message(response)
22
+ when 500
23
+ raise Guidestar::InternalServerError, error_message(response)
24
+ when 501
25
+ raise Guidestar::NotImplemented, error_message(response)
26
+ when 502
27
+ raise Guidestar::BadGateway, error_message(response)
28
+ when 503
29
+ raise Guidestar::ServiceUnavailable, error_message(response)
30
+ end
31
+ end
32
+
33
+ def error_message(response)
34
+ "#{response[:description]}\n#{response[:body]}"
35
+ end
36
+ end
37
+ end
38
+
data/lib/guidestar.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "faraday"
2
+ require "faraday_middleware"
3
+ require "guidestar/version"
4
+ require "guidestar/client"
5
+ require "guidestar/error"
6
+ require "guidestar/result"
7
+
8
+ module Guidestar
9
+ class << self
10
+ attr_accessor :username
11
+ attr_accessor :password
12
+ attr_accessor :proxy
13
+ attr_accessor :default_endpoint
14
+
15
+ def configure
16
+ yield self
17
+ true
18
+ end
19
+ end
20
+
21
+ Faraday.register_middleware :response,
22
+ :raise_guidestar_error => lambda { Faraday::Response::RaiseGuidestarError }
23
+ end
@@ -0,0 +1,75 @@
1
+ require 'forwardable'
2
+ require 'faraday/response/raise_guidestar_error'
3
+ require 'guidestar/request'
4
+ require 'guidestar/connection'
5
+ require 'guidestar/client/search'
6
+
7
+ module Guidestar
8
+ class Client
9
+
10
+ extend Forwardable
11
+
12
+ include Guidestar::Request
13
+ include Guidestar::Connection
14
+ include Guidestar::Client::Search
15
+
16
+ attr_reader :proxy
17
+
18
+ # Public: Sets up the core Client object that can be reused throughout
19
+ # the request.
20
+ def initialize(options={})
21
+ @api_url = options.delete(:endpoint) || Guidestar.default_endpoint
22
+ @proxy = options.delete(:proxy) || Guidestar.proxy
23
+ @username = options.delete(:username) || Guidestar.username
24
+ @password = options.delete(:password) || Guidestar.password
25
+ @options = options.reverse_merge!(:version => 1.0,
26
+ :limit => 25,
27
+ :page => 1 )
28
+ end
29
+
30
+ # Internal: Provides the URL for accessing the API
31
+ #
32
+ # Returns a String to the API root url.
33
+ def api_url
34
+ @api_url ||= 'https://gsservices.guidestar.org'
35
+ end
36
+
37
+ # Internal: Allows method chaining of parameters to create template
38
+ # objects.
39
+ #
40
+ # Returns a Guidestar::Chain object that mimics the Client.
41
+ def method_missing(method_name, *args)
42
+ chain = Chain.new({
43
+ :publisher => @publisher,
44
+ :endpoint => @api_url,
45
+ :proxy => @proxy
46
+ }.merge(@options))
47
+ chain.send(method_name.to_sym, *args)
48
+ chain
49
+ end
50
+ private
51
+
52
+ # Internal: Provides the default headers when making a request
53
+ #
54
+ # Returns a Hash of request headers.
55
+ def default_headers
56
+ headers = {
57
+ :user_agent => 'Guidestar Ruby Gem',
58
+ :accept => 'application/xml'
59
+ }
60
+ end
61
+
62
+ end
63
+
64
+ class Chain < Client
65
+ attr_accessor :options
66
+ def initialize(*args)
67
+ @options = {}
68
+ super
69
+ end
70
+ def method_missing(method_name, *args)
71
+ @options[method_name.to_sym]=args.first
72
+ self
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,22 @@
1
+ module Guidestar
2
+ class Client
3
+ module Search
4
+ def search(options={})
5
+ path = '/GuideStarBasic'
6
+ get(path, options)
7
+ end
8
+ def detailed_search(options={})
9
+ path = '/GuideStarDetail'
10
+ get(path, options)
11
+ end
12
+ def charity_check(options={})
13
+ path = '/GuideStarCharityCheck'
14
+ get(path, options)
15
+ end
16
+ def npo_validation(options={})
17
+ path = '/GuideStarNPOValidation'
18
+ get(path, options)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module Guidestar
2
+ module Connection
3
+ # Raw HTTPS connection with Faraday::Connection
4
+ #
5
+ # @return [Faraday::Connection]
6
+ def connection
7
+ return @connection if @connection
8
+ params = {}
9
+ @connection = Faraday.new(:url => api_url, :params => params, :headers => default_headers) do |conn|
10
+ conn.response :mashify
11
+ conn.response :xml, :content_type => /\bxml$/
12
+ conn.response :raise_guidestar_error
13
+
14
+ conn.adapter Faraday.default_adapter
15
+ end
16
+ @connection.proxy(self.proxy) if self.proxy
17
+ @connection
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ module Guidestar
2
+ # Custom error class for rescuing from all Guidestar errors
3
+ class Error < StandardError; end
4
+
5
+ # Raised when Guidestar returns a 303 HTTP status code
6
+ class SeeOther < Error; end
7
+
8
+ # Raised when Guidestar returns a 400 HTTP status code
9
+ class BadRequest < Error; end
10
+
11
+ # Raised when Guidestar returns a 401 HTTP status code
12
+ class Unauthorized < Error; end
13
+
14
+ # Raised when Guidestar returns a 403 HTTP status code
15
+ class Forbidden < Error; end
16
+
17
+ # Raised when Guidestar returns a 404 HTTP status code
18
+ class NotFound < Error; end
19
+
20
+ # Raised when Guidestar returns a 406 HTTP status code
21
+ class NotAcceptable < Error; end
22
+
23
+ # Raised when Guidestar returns a 422 HTTP status code
24
+ class UnprocessableEntity < Error; end
25
+
26
+ # Raised when Guidestar returns a 500 HTTP status code
27
+ class InternalServerError < Error; end
28
+
29
+ # Raised when Guidestar returns a 501 HTTP status code
30
+ class NotImplemented < Error; end
31
+
32
+ # Raised when Guidestar returns a 502 HTTP status code
33
+ class BadGateway < Error; end
34
+
35
+ # Raised when Guidestar returns a 503 HTTP status code
36
+ class ServiceUnavailable < Error; end
37
+
38
+ # Raised when missing information is detected in the wrapper
39
+ class MissingInformation < Error; end
40
+ end
41
+
@@ -0,0 +1,53 @@
1
+ module Guidestar
2
+ module Request
3
+
4
+ def get(path, data={})
5
+ Guidestar::Result.new(get_raw(path, data),path,self)
6
+ end
7
+
8
+ def get_raw(path, data={})
9
+ response = connection.get do |request|
10
+ request.url("/GuideStar_SearchService/searchservice.asmx#{path}", set_params(data))
11
+ end
12
+ response if response.status == 200
13
+ end
14
+
15
+ private
16
+
17
+ def set_params(data={})
18
+ @options.merge!(data)
19
+ @options[:page_size] = @options.delete(:limit) if @options[:limit]
20
+ @options[:page_size] = @options.delete(:per) if @options[:per]
21
+ @options[:zip_radius] = @options.delete(:zipradius) if @options[:zipradius]
22
+ @options[:org_name] = @options.delete(:name) if @options[:name]
23
+ @options[:offset] = (@options.delete(:page)-1) if @options[:page]
24
+ builder = Nokogiri::XML::Builder.new do |xml|
25
+ xml.query do
26
+ xml.version @options[:version]
27
+ xml.login @username
28
+ xml.password @password
29
+ xml.pageSize @options[:page_size]
30
+ xml.offset @options[:offset]
31
+ xml.keyword @options[:keyword] if @options[:keyword]
32
+ xml.city @options[:city] if @options[:city]
33
+ xml.state @options[:state] if @options[:state]
34
+ xml.zip @options[:zip] if @options[:zip]
35
+ zml.zipradius @options[:zip_radius] if @options[:zip_radius]
36
+ xml.ein @options[:ein] if @options[:ein]
37
+ xml.orgName @options[:org_name] if @options[:org_name]
38
+ if @options[:categories] && @options[:categories].is_a?(Array)
39
+ @options[:categories].each {|category| xml.category category }
40
+ end
41
+
42
+ if @options[:sub_categories] && @options[:sub_categories].is_a?(Array)
43
+ @options[:sub_categories].each {|sub_category| xml.subCategory sub_category }
44
+ end
45
+
46
+ xml.nteeCode @options[:ntee_code] if @options[:ntee_code]
47
+ end
48
+ end
49
+ {:xmlInput => builder.to_xml}
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,90 @@
1
+ module Guidestar
2
+ class Result
3
+ #
4
+ # Public: Returns the String xml of the response from Guidestar
5
+ attr_reader :xml
6
+
7
+ # Public: Returns the Integer number of results from the query
8
+ attr_reader :total_count
9
+
10
+ # Public: Returns the Float time in seconds to search
11
+ attr_reader :search_time
12
+
13
+ # Public: Returns an Array of organizations from the search
14
+ def organizations
15
+ return @organizations if @organizations
16
+ parse_xml(@client.get_raw(@path, @options))
17
+ @organizations
18
+ end
19
+
20
+ def initialize(raw_response, path, client)
21
+ @path = path
22
+ @client = client
23
+ parse_xml(raw_response)
24
+ end
25
+
26
+ private
27
+
28
+ def parse_xml(raw_response)
29
+ @xml = ::MultiXml.parse(raw_response.body.string)['root']
30
+ @total_count = @xml['totalResults'].to_i
31
+ @search_time = @xml['searchTime'].to_f
32
+ @options = {}
33
+
34
+ @organizations = []
35
+ orgs = @xml['organizations']['organization']
36
+ orgs = [orgs] unless orgs.is_a?(Array)
37
+ orgs.each do |org|
38
+ org = Hashie::Mash.new clean_keys(org)
39
+
40
+ org.delete(:general_information).each do |k,v|
41
+ org[k]=v
42
+ end
43
+ org.delete(:mission_and_programs).each do |type, content|
44
+ content = Nokogiri::HTML content
45
+ content = content.text.encode(*encoding_options).strip
46
+ org[type] = content unless content == 'No information currently in database.'
47
+ end
48
+
49
+ org[:name] = org.delete :org_name
50
+ org[:tax_deductible] = org[:deductibility] == 'Contributions are deductible, as provided by law'
51
+ org[:result_position] = org[:result_position].to_i
52
+
53
+ ein = org[:ein]
54
+ def ein.to_i; self.gsub('-','').to_i; end
55
+
56
+ @organizations << org
57
+ end
58
+ end
59
+
60
+ def clean_keys(value)
61
+ case value
62
+ when Array
63
+ value.map { |v| clean_keys v }
64
+ when Hash
65
+ Hash[value.map { |k, v| [k.gsub(/(.)([A-Z])/,'\1_\2').downcase.to_sym, clean_keys(v)] }]
66
+ else
67
+ value.nil? ? nil : value.strip
68
+ end
69
+ end
70
+
71
+ def encoding_options
72
+ @encoding_options ||= [
73
+ Encoding.find('ASCII'),
74
+ {
75
+ :invalid => :replace, # Replace invalid byte sequences
76
+ :undef => :replace, # Replace anything not defined in ASCII
77
+ :replace => '', # Use a blank for those replacements
78
+ :universal_newline => true # Always break lines with \n
79
+ }
80
+ ]
81
+ end
82
+ def method_missing(method_name, *args)
83
+ @options[method_name.to_sym]=args.first
84
+ @organizations = nil
85
+ self
86
+ end
87
+ end
88
+ end
89
+
90
+
@@ -0,0 +1,3 @@
1
+ module Guidestar
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guidestar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kelly Martin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.8'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - !ruby/object:Gem::Dependency
31
+ name: faraday_middleware
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0.9'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '0.9'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rash
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.3'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: multi_xml
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.5'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.5'
78
+ - !ruby/object:Gem::Dependency
79
+ name: nokogiri
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '1.5'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '1.5'
94
+ description: Allows access to the Guidestar API
95
+ email:
96
+ - kellymartinv@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - guidestar.gemspec
107
+ - lib/faraday/response/raise_guidestar_error.rb
108
+ - lib/guidestar.rb
109
+ - lib/guidestar/client.rb
110
+ - lib/guidestar/client/search.rb
111
+ - lib/guidestar/connection.rb
112
+ - lib/guidestar/error.rb
113
+ - lib/guidestar/request.rb
114
+ - lib/guidestar/result.rb
115
+ - lib/guidestar/version.rb
116
+ homepage: http://github.com/kellym/guidestar
117
+ licenses: []
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 1.8.25
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: Use this gem to access the Guidestar API
140
+ test_files: []