guidestar 0.0.1

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,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: []