fullcontacter 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.document +5 -0
  2. data/.gitignore +53 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.md +20 -0
  6. data/README.md +36 -0
  7. data/Rakefile +25 -0
  8. data/VERSION +1 -0
  9. data/bugs.txt +2 -0
  10. data/fullcontact.gemspec +34 -0
  11. data/lib/faraday/request/gateway.rb +18 -0
  12. data/lib/faraday/response/fullcontact_errors.rb +33 -0
  13. data/lib/faraday/response/raise_http_4xx.rb +45 -0
  14. data/lib/faraday/response/raise_http_5xx.rb +24 -0
  15. data/lib/fullcontact.rb +27 -0
  16. data/lib/fullcontact/api.rb +21 -0
  17. data/lib/fullcontact/client.rb +32 -0
  18. data/lib/fullcontact/client/batch_process.rb +35 -0
  19. data/lib/fullcontact/client/contact.rb +119 -0
  20. data/lib/fullcontact/client/contact_list.rb +84 -0
  21. data/lib/fullcontact/client/icon.rb +35 -0
  22. data/lib/fullcontact/client/name.rb +167 -0
  23. data/lib/fullcontact/client/person.rb +94 -0
  24. data/lib/fullcontact/client/provisioning.rb +28 -0
  25. data/lib/fullcontact/client/snapshot.rb +31 -0
  26. data/lib/fullcontact/client/subscription.rb +45 -0
  27. data/lib/fullcontact/client/user.rb +28 -0
  28. data/lib/fullcontact/configuration.rb +95 -0
  29. data/lib/fullcontact/connection.rb +36 -0
  30. data/lib/fullcontact/error.rb +35 -0
  31. data/lib/fullcontact/request.rb +43 -0
  32. data/lib/fullcontact/version.rb +3 -0
  33. data/spec/faraday/response_spec.rb +56 -0
  34. data/spec/fixtures/clear_contact_list.json +3 -0
  35. data/spec/fixtures/contact_history.json +16 -0
  36. data/spec/fixtures/create_contact_list.json +4 -0
  37. data/spec/fixtures/create_snapshot.json +7 -0
  38. data/spec/fixtures/create_subscription.json +4 -0
  39. data/spec/fixtures/deduce_by_email.json +13 -0
  40. data/spec/fixtures/deduce_by_username.json +13 -0
  41. data/spec/fixtures/delete_contact.json +4 -0
  42. data/spec/fixtures/delete_contact_list.json +3 -0
  43. data/spec/fixtures/delete_subscription.json +3 -0
  44. data/spec/fixtures/get_contact.json +20 -0
  45. data/spec/fixtures/get_contact_lists.json +11 -0
  46. data/spec/fixtures/get_contacts_in_a_list.json +41 -0
  47. data/spec/fixtures/get_enriched_contact.json +261 -0
  48. data/spec/fixtures/get_updates.json +252 -0
  49. data/spec/fixtures/has_enriched_updates.json +4 -0
  50. data/spec/fixtures/list_snapshots.json +7 -0
  51. data/spec/fixtures/list_subscriptions.json +10 -0
  52. data/spec/fixtures/normalize.json +27 -0
  53. data/spec/fixtures/parse.json +10 -0
  54. data/spec/fixtures/person.json +47 -0
  55. data/spec/fixtures/queue_contact_list_for_enrichment.json +3 -0
  56. data/spec/fixtures/save_enriched_contact.json +261 -0
  57. data/spec/fixtures/similarity.json +45 -0
  58. data/spec/fixtures/stats_by_family_name.json +12 -0
  59. data/spec/fixtures/stats_by_given_and_family_name.json +62 -0
  60. data/spec/fixtures/stats_by_given_name.json +57 -0
  61. data/spec/fixtures/stats_by_name.json +64 -0
  62. data/spec/fixtures/update_contact.json +9 -0
  63. data/spec/fullcontact/api_spec.rb +68 -0
  64. data/spec/fullcontact/client/contact_list_spec.rb +89 -0
  65. data/spec/fullcontact/client/contact_spec.rb +108 -0
  66. data/spec/fullcontact/client/icon_spec.rb +24 -0
  67. data/spec/fullcontact/client/name_spec.rb +121 -0
  68. data/spec/fullcontact/client/person_spec.rb +77 -0
  69. data/spec/fullcontact/client/snapshot_spec.rb +35 -0
  70. data/spec/fullcontact/client/subscription_spec.rb +47 -0
  71. data/spec/fullcontact/client_spec.rb +10 -0
  72. data/spec/fullcontact_spec.rb +114 -0
  73. data/spec/helper.rb +39 -0
  74. metadata +384 -0
@@ -0,0 +1,28 @@
1
+ module FullContact
2
+ class Client
3
+ module Provisioning
4
+ # Public:The Provisioning method creates a new API key based on an
5
+ # Account Key. This method is useful when your application has many end
6
+ # users that you would like to track separately. An account key is
7
+ # required for accessing this api method. This account key can be
8
+ # initialized through the configure method. For getting an account key,
9
+ # send an email to support@fullcontact.com.
10
+ #
11
+ # Example
12
+ #
13
+ # api_key = FullContact.create_new_api_key
14
+ #
15
+ # Returns a hash which contains the generated api_key and monthly quota
16
+ def create_new_api_key
17
+ # return error if no provisioning key defined
18
+ return unless FullContact.options[:account_key]
19
+ self.endpoint = 'https://api.fullcontact.com/apiKey'
20
+ options = {:accountKey => FullContact.options[:account_key]}
21
+ get('new', options)
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,31 @@
1
+ module FullContact
2
+ class Client
3
+ module Snapshot
4
+ # Public: Creates a snapshot in order to store a point-in-time backup of a contactList
5
+ #
6
+ # list_id - id of the contact list to be backed-up
7
+ # options - hash containing additonal arguments
8
+ # :name - Name of the snapshot
9
+ #
10
+ # Example
11
+ #
12
+ # response = FullContact.create_snapshot(list_id, {:name => 'foo'})
13
+ # response.result now contains the snapshot name and timestamp
14
+ def create_snapshot(list_id, options)
15
+ post("contactList/#{list_id}/snapshot", options)
16
+ end
17
+
18
+ # Public: List all snapshots associated with a contact list
19
+ #
20
+ # list_id - id of the contact list for which snapshots need to be fetched
21
+ #
22
+ # Example
23
+ #
24
+ # response = FullContact.list_snapshots(list_id)
25
+ # response.snapshots gives a list of snapshot names
26
+ def list_snapshots(list_id)
27
+ get("contactList/#{list_id}/snapshot")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ module FullContact
2
+ class Client
3
+ module Subscription
4
+ # Public: Creates a subscription to a contactList in order to receive webhook notifications for certain events
5
+ #
6
+ # list_id - id of the contact list for which subscription is to be created
7
+ # options - hash containing additional arguments
8
+ # :event Type of event. Only 'enriched' is supported right now
9
+ # :callback Callback URL to post to when event occurs
10
+ #
11
+ # Example
12
+ #
13
+ # response = FullContact.create_subscription(list_id, {:event => 'enriched', :callback => callback_url })
14
+ # response.id contains the subscription id
15
+ def create_subscription(list_id, options)
16
+ post("contactList/#{list_id}/subscribe", options)
17
+ end
18
+
19
+ # Public: Lists all subscriptions associated with a contactList
20
+ #
21
+ # list_id - id of the contact list for which subscription is to be created
22
+ #
23
+ # Example
24
+ #
25
+ # response = FullContact.list_subscriptions(list_id)
26
+ # response.subscriptions contains list of all subscriptions for this contact list
27
+ def list_subscriptions(list_id)
28
+ get("contactList/#{list_id}/subscribe")
29
+ end
30
+
31
+ # Public: Delete a subscription associated with a contactList
32
+ #
33
+ # list_id - id of the contact list for which subscription is to be created
34
+ # options - hash containing additional arguments
35
+ # :subscription id of the subscription to delete
36
+ #
37
+ # Example
38
+ #
39
+ # response = FullContact.delete_subscriptions(list_id, {:subscription => subscription_id})
40
+ def delete_subscription(list_id, options)
41
+ delete("contactList/#{list_id}/subscribe", options)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ module FullContact
2
+ class Client
3
+ module User
4
+ # Public: Authenticate a user using the username and password. If
5
+ # authenticated, sets the returned access_token in a access_token config
6
+ # variable
7
+ #
8
+ # options - a hash containing the user's username and password
9
+ #
10
+ # Example
11
+ #
12
+ # FullContact.authenticate({ :username => 'prafullakiran@gmail.com',
13
+ # :password => 'grizzlybear' })
14
+ # # we're authenticated now
15
+ # contact_lists = FullContact.get_contact_lists
16
+ def authenticate(options = {})
17
+ self.endpoint = 'https://api.fullcontact.com/auth/'
18
+ self.format = ''
19
+ access_token = post('token', options)
20
+
21
+ FullContact.configure do |config|
22
+ config.access_token = access_token
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,95 @@
1
+ require 'faraday'
2
+
3
+ module FullContact
4
+ # Defines constants and methods related to configuration
5
+ module Configuration
6
+ # An array of valid keys in the options hash when configuring a {FullContact::API}
7
+ VALID_OPTIONS_KEYS = [
8
+ :adapter,
9
+ :api_key,
10
+ :account_key,
11
+ :get_request_url_only,
12
+ :endpoint,
13
+ :format,
14
+ :access_token,
15
+ :gateway,
16
+ :proxy,
17
+ :user_agent].freeze
18
+
19
+ # An array of valid request/response formats
20
+ #
21
+ # @note Not all methods support the XML format.
22
+ VALID_FORMATS = [
23
+ :json,
24
+ :xml].freeze
25
+
26
+ # The adapter that will be used to connect if none is set
27
+ #
28
+ # @note The default faraday adapter is Net::HTTP.
29
+ DEFAULT_ADAPTER = Faraday.default_adapter
30
+
31
+ # By default, don't set an api key
32
+ DEFAULT_API_KEY = nil
33
+
34
+ # By default, don't set an access key
35
+ DEFAULT_ACCESS_TOKEN = nil
36
+
37
+ # By default, don't set an account key
38
+ DEFAULT_ACCOUNT_KEY = nil
39
+
40
+ # By default, get full response
41
+ GET_REQUEST_URL_ONLY = false
42
+
43
+ # The endpoint that will be used to connect if none is set
44
+ #
45
+ DEFAULT_ENDPOINT = 'https://api.fullcontact.com/v2/'.freeze
46
+
47
+ # The response format appended to the path and sent in the 'Accept' header if none is set
48
+ #
49
+ # @note JSON is preferred over XML because it is more concise and faster to parse.
50
+ DEFAULT_FORMAT = :json
51
+
52
+ # By default, don't use a proxy server
53
+ DEFAULT_PROXY = nil
54
+
55
+ # The user agent that will be sent to the API endpoint if none is set
56
+ DEFAULT_USER_AGENT = "FullContact Ruby Gem".freeze
57
+
58
+ DEFAULT_GATEWAY = nil
59
+
60
+ # @private
61
+ attr_accessor *VALID_OPTIONS_KEYS
62
+
63
+ # When this module is extended, set all configuration options to their default values
64
+ def self.extended(base)
65
+ base.reset
66
+ end
67
+
68
+ # Convenience method to allow configuration options to be set in a block
69
+ def configure
70
+ yield self
71
+ end
72
+
73
+ # Create a hash of options and their values
74
+ def options
75
+ options = {}
76
+ VALID_OPTIONS_KEYS.each{|k| options[k] = send(k) }
77
+ options
78
+ end
79
+
80
+ # Reset all configuration options to defaults
81
+ def reset
82
+ self.adapter = DEFAULT_ADAPTER
83
+ self.api_key = DEFAULT_API_KEY
84
+ self.access_token = DEFAULT_ACCESS_TOKEN
85
+ self.account_key = DEFAULT_ACCOUNT_KEY
86
+ self.get_request_url_only = GET_REQUEST_URL_ONLY
87
+ self.endpoint = DEFAULT_ENDPOINT
88
+ self.format = DEFAULT_FORMAT
89
+ self.proxy = DEFAULT_PROXY
90
+ self.user_agent = DEFAULT_USER_AGENT
91
+ self.gateway = DEFAULT_GATEWAY
92
+ self
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,36 @@
1
+ require 'faraday_middleware'
2
+ require 'faraday/request/gateway'
3
+ require 'faraday/response/fullcontact_errors'
4
+
5
+
6
+ module FullContact
7
+ # @private
8
+ module Connection
9
+ private
10
+
11
+ def connection(raw=false)
12
+ options = {
13
+ :headers => {'Accept' => "application/#{format}", 'User-Agent' => user_agent},
14
+ :proxy => proxy,
15
+ :ssl => {:verify => false},
16
+ :url => api_endpoint,
17
+ }
18
+
19
+ Faraday.new(options) do |builder|
20
+ builder.use Faraday::Request::UrlEncoded
21
+ builder.use Faraday::Request::Gateway, gateway if gateway
22
+ builder.use Faraday::Response::Rashify unless raw
23
+ unless raw
24
+ case format.to_s.downcase
25
+ when 'json'
26
+ builder.use Faraday::Response::ParseJson
27
+ when 'xml'
28
+ builder.use Faraday::Response::ParseXml
29
+ end
30
+ end
31
+ builder.use Faraday::Response::FullContactErrors
32
+ builder.adapter Faraday.default_adapter
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ module FullContact
2
+ # Custom error class for rescuing from all FullContact errors
3
+ class Error < StandardError
4
+ attr_reader :http_headers
5
+
6
+ def initialize(message, http_headers)
7
+ @http_headers = Hash[http_headers]
8
+ super message
9
+ end
10
+ end
11
+
12
+ # Raised when FullContact returns the HTTP status code 400
13
+ class BadRequest < Error; end
14
+
15
+ # Raised when FullContact returns the HTTP status code 401
16
+ class Unauthorized < Error; end
17
+
18
+ # Raised when FullContact returns the HTTP status code 403
19
+ class Forbidden < Error; end
20
+
21
+ # Raised when FullContact returns the HTTP status code 404
22
+ class NotFound < Error; end
23
+
24
+ # Raised when FullContact returns the HTTP status code 422
25
+ class Invalid < Error; end
26
+
27
+ # Raised when FullContact returns the HTTP status code 500
28
+ class InternalServerError < Error; end
29
+
30
+ # Raised when FullContact returns the HTTP status code 502
31
+ class BadGateway < Error; end
32
+
33
+ # Raised when FullContact returns the HTTP status code 503
34
+ class ServiceUnavailable < Error; end
35
+ end
@@ -0,0 +1,43 @@
1
+ module FullContact
2
+ # Defines HTTP request methods
3
+ module Request
4
+ # Perform an HTTP GET request
5
+ def get(path, options={}, raw=false)
6
+ request(:get, path, options, raw)
7
+ end
8
+
9
+ # Perform an HTTP POST request
10
+ def post(path, options={}, raw=false)
11
+ request(:post, path, options, raw)
12
+ end
13
+
14
+ # Perform an HTTP DELETE request
15
+ def delete(path, options={}, raw=false)
16
+ request(:delete, path, options, raw)
17
+ end
18
+
19
+ private
20
+
21
+ # Perform an HTTP request
22
+ def request(method, path, options, raw=false)
23
+ if FullContact.options[:get_request_url_only]
24
+ return connection(raw).build_url(formatted_path(path), options)
25
+ end
26
+ options[:apiKey] = FullContact.options[:api_key]
27
+ unless FullContact.options[:access_token].nil?
28
+ options[:accessToken] = FullContact.options[:access_token]
29
+ end
30
+ response = connection(raw).send(method) do |request|
31
+ request.url(formatted_path(path), options)
32
+ request.headers["Content-Type"] = options[:content_type] if options.include?(:content_type)
33
+ request.body = options[:request_body] if options.include?(:request_body)
34
+ end
35
+ raw ? response : response.body
36
+ end
37
+
38
+ def formatted_path(path)
39
+ return path if format.to_s.empty?
40
+ [path, format].compact.join('.')
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module FullContact
2
+ VERSION = "0.3.2"
3
+ end
@@ -0,0 +1,56 @@
1
+ require 'helper'
2
+ require 'faraday'
3
+ require 'fullcontact'
4
+
5
+ describe Faraday::Response do
6
+ before do
7
+ FullContact.configure do |config|
8
+ config.api_key = "api_key"
9
+ end
10
+ @client = FullContact::Client.new
11
+ end
12
+
13
+ {
14
+ 400 => FullContact::BadRequest,
15
+ 401 => FullContact::Unauthorized,
16
+ 403 => FullContact::Forbidden,
17
+ 404 => FullContact::NotFound,
18
+ 422 => FullContact::Invalid,
19
+ 500 => FullContact::InternalServerError,
20
+ 502 => FullContact::BadGateway,
21
+ 503 => FullContact::ServiceUnavailable,
22
+ }.each do |status, exception|
23
+ if (status >= 500)
24
+ context "when HTTP status is #{status}" do
25
+ before do
26
+ stub_get('person.json').
27
+ with(:query => {:apiKey => "api_key", :email => 'brawest@gmail.com'}).
28
+ to_return(:status => status)
29
+ end
30
+
31
+ it "should raise #{exception.name} error" do
32
+ lambda do
33
+ @client.lookup_by_email('brawest@gmail.com')
34
+ end.should raise_error(exception)
35
+ end
36
+ end
37
+ else
38
+ [nil, "error", "errors"].each do |body|
39
+ context "when HTTP status is #{status} and body is #{body||='nil'}" do
40
+ before do
41
+ body_message = '{"'+body+'":"test"}' unless body.nil?
42
+ stub_get('person.json').
43
+ with(:query => {:apiKey => "api_key", :email => 'brawest@gmail.com'}).
44
+ to_return(:status => status, :body => body_message)
45
+ end
46
+
47
+ it "should raise #{exception.name} error" do
48
+ lambda do
49
+ @client.lookup_by_email('brawest@gmail.com')
50
+ end.should raise_error(exception)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "status": 200
3
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "history":
3
+ [
4
+ {
5
+ "eTag": "fffffec9b5094cf18aaef4da318436755124a12d2422eaf2c9c44b95",
6
+ "date": "2012-03-25T17:45:43.441Z",
7
+ "action": "Enriched"
8
+ },
9
+ {
10
+ "eTag": "fffffec9b536c589363364e51a5dc9800f54d11cdbf1a21fe94ef35b",
11
+ "date": "2012-03-25T16:56:03.448Z",
12
+ "action": "Added"
13
+ }
14
+ ],
15
+ "status": 200
16
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "listId": "fd4e7ca63f79ea5113b2a2ebcf0759c5ebecc250",
3
+ "status": 200
4
+ }