leadspend 1.0.2

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.
Binary file
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
@@ -0,0 +1,14 @@
1
+ === 1.0.2 / 2012-08-23
2
+ * Moved username and password into options for client initialization
3
+
4
+ === 1.0.1 / 2012-08-23
5
+ * Added configurable JSON backends with reasonable defaults
6
+ * to use a particular backend, the supporting gem(s) must be installed (Yajl, JSON, Rails)
7
+ * Added support for the "role", "timeout", "retry" extended attributes on results
8
+ * Now using Hoe for gemspec
9
+ * Added MIT-LICENSE
10
+
11
+ === 1.0.0 / 2012-08-22
12
+ * Support for Leadspend API according to their spec documentation.
13
+ * unit tests require the fakeweb gem.
14
+
@@ -0,0 +1,14 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/leadspend.rb
7
+ lib/leadspend/exceptions.rb
8
+ lib/leadspend/result.rb
9
+ lib/leadspend/client.rb
10
+ lib/leadspend/parser/json_parser.rb
11
+ lib/leadspend/parser/yajl_parser.rb
12
+ lib/leadspend/parser/rails_parser.rb
13
+ test/unit/test_leadspend_client.rb
14
+ test/mocks/leadspend/server.rb
@@ -0,0 +1,59 @@
1
+ = leadspend
2
+
3
+ * http://www.github.com/justindossey/leadspend
4
+
5
+ == DESCRIPTION:
6
+ Leadspend client access library.
7
+
8
+ == SYNOPSIS:
9
+
10
+ client = Leadspend::Client.new(:username => LEADSPEND_USERNAME,
11
+ :password => LEADSPEND_PASSWORD,
12
+ :ca_file => CA_FILE,
13
+ :timeout => 5)
14
+ is_valid_email = client.validate(params[:email]) # true if verified or unknown, false otherwise
15
+
16
+ == REQUIREMENTS:
17
+
18
+ * Ruby (of course) with OpenSSL support
19
+ * Your preferred JSON gem (json, yajl), or ActiveSupport if you use Rails
20
+ * FakeWeb for testing: https://github.com/chrisk/fakeweb
21
+ * Hoe for building the gem
22
+
23
+ == INSTALL:
24
+
25
+ * sudo gem install leadspend
26
+
27
+ == DEVELOPERS
28
+
29
+ Read the source!
30
+ After checking out the source, run:
31
+
32
+ $ rake newb
33
+
34
+ This task will install any missing dependencies, run the tests/specs,
35
+ and generate the RDoc.
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2012 Justin Dossey.
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
59
+
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ # Hoe.plugin :compiler
7
+ # Hoe.plugin :gem_prelude_sucks
8
+ # Hoe.plugin :inline
9
+ # Hoe.plugin :racc
10
+ # Hoe.plugin :rcov
11
+ # Hoe.plugin :rubyforge
12
+
13
+ Hoe.spec 'leadspend' do
14
+ developer('Justin Dossey', 'jbd@podomatic.com')
15
+ end
16
+
17
+ # vim: syntax=ruby
@@ -0,0 +1,18 @@
1
+ ##
2
+ # Leadspend API implementation for Ruby
3
+ # = Leadspend
4
+ # This (top-level) module contains constants based on the API specification.
5
+ module Leadspend
6
+ VERSION = '1.0.2'
7
+ DEFAULT_SERVERS = %w{primary.api.leadspend.com secondary.api.leadspend.com}
8
+ DEFAULT_VERSION = "v2"
9
+ MIN_TIMEOUT = 3
10
+ MAX_TIMEOUT = 15
11
+ RESULT_STATUSES = ['unknown','verified','disposable', 'unreachable', 'undeliverable', 'illegitimate']
12
+ end
13
+ require "#{File.dirname(__FILE__)}/leadspend/exceptions"
14
+ require "#{File.dirname(__FILE__)}/leadspend/parser"
15
+ require "#{File.dirname(__FILE__)}/leadspend/result"
16
+ require "#{File.dirname(__FILE__)}/leadspend/client"
17
+
18
+
@@ -0,0 +1,138 @@
1
+ require 'net/https'
2
+ ##
3
+ # = Leadspend Client
4
+ # The primary interface to Leadspend.
5
+ # Use it like so:
6
+ # client = Leadspend::Client.new(LEADSPEND_USERNAME, LEADSPEND_PASSWORD, :ca_file => CA_FILE, :timeout => 5)
7
+ # is_valid_email = client.validate(params[:email) # true if verified or unknown, false otherwise
8
+ # If you want more information about the response, use something like
9
+ # leadspend_result = client.fetch_result(params[:email])
10
+ # This will return a Leadspend::Result object representing the JSON response,
11
+ # with convenience methods like unreachable? and illegitimate?.
12
+
13
+ class Leadspend::Client
14
+ # Instantiate a client.
15
+ # Recommended options: :ca_file is the full path to a CA Cert file.
16
+ # :timeout is the server-side timeout in seconds, between 3 and 15. If a
17
+ # result is not available within the timeout, the response will be an
18
+ # "unknown" result.
19
+ def initialize(opts={})
20
+ options = opts
21
+ if defined?(HashWithIndifferentAccess)
22
+ options = HashWithIndifferentAccess.new(opts)
23
+ end
24
+ @username = options[:username]
25
+ @password = options[:password]
26
+ if @username.nil? or @password.nil?
27
+ raise Leadspend::Exceptions::LeadspendException, "No username or password specified!"
28
+ end
29
+ @servers = options[:servers] || Leadspend::DEFAULT_SERVERS
30
+ @api_version = options[:version] || Leadspend::DEFAULT_VERSION
31
+ # path to the CA file: download http://curl.haxx.se/ca/cacert.pem and put
32
+ # it someplace on your server.
33
+ @ca_file = options[:ca_file]
34
+
35
+ # set the JSON parser to use. Use the one specified, or choose a reasonable default.
36
+ case options[:json_parser]
37
+ when 'yajl'
38
+ require "#{File.dirname(__FILE__)}/parser/yajl_parser"
39
+ Leadspend::Result.json_parser=Leadspend::Parser::YajlParser
40
+ when 'rails'
41
+ require "#{File.dirname(__FILE__)}/parser/rails_parser"
42
+ Leadspend::Result.json_parser=Leadspend::Parser::RailsParser
43
+ when 'json'
44
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
45
+ Leadspend::Result.json_parser=Leadspend::Parser::JSONParser
46
+ else
47
+ if defined? Rails
48
+ require "#{File.dirname(__FILE__)}/parser/rails_parser"
49
+ Leadspend::Result.json_parser=Leadspend::Parser::RailsParser
50
+ else
51
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
52
+ Leadspend::Result.json_parser=Leadspend::Parser::JSONParser
53
+ end
54
+ end
55
+
56
+ @server_index = 0
57
+
58
+ @request_options = {}
59
+ # optional: allow a server timeout. Minimum is 3, max is 15
60
+ if options[:timeout]
61
+ @request_options[:timeout] = options[:timeout].to_i
62
+ if @request_options[:timeout] < Leadspend::MIN_TIMEOUT
63
+ @request_options[:timeout] = Leadspend::MIN_TIMEOUT
64
+ elsif @request_options[:timeout] > Leadspend::MAX_TIMEOUT
65
+ @request_options[:timeout] = Leadspend::MAX_TIMEOUT
66
+ end
67
+ end
68
+ end
69
+
70
+ # Return a boolean based on whether an address is valid or not.
71
+ # Valid statuses: unknown, validated.
72
+ # Invalid statuses: anything else.
73
+ def validate(address)
74
+ result = fetch_result(address)
75
+ return result.verified? || result.unknown?
76
+ end
77
+
78
+ # fetch a result from Leadspend, doing failover if necessary. R
79
+ # Returns a Leadspend::Result object if successful, or an exception if there was a failure.
80
+ def fetch_result(address)
81
+ retry_once = true
82
+ begin
83
+ result = query("/#{@api_version}/validity", address, @request_options)
84
+ rescue Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::ECONNRESET, IOError,
85
+ Leadspend::Exceptions::ServerException, Leadspend::Exceptions::ServerBusyException
86
+ if retry_once
87
+ retry_once = false
88
+ @server_index = (@server_index + 1) % @servers.length
89
+ retry
90
+ else
91
+ raise $!
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+ # do a full uri escape on a value for HTTP
98
+ def escape_param(param) # :nodoc:
99
+ URI::escape(param.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
100
+ end
101
+
102
+ # Do a request to Leadspend and return a Leadspend::Result or exception.
103
+ def query(base, address, param_hash) # :nodoc:
104
+ http = Net::HTTP.new(@servers[@server_index], 443)
105
+ http.use_ssl = true
106
+ if @ca_file
107
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
108
+ http.ca_file = @ca_file
109
+ end
110
+ if param_hash.empty?
111
+ request_path = [base, escape_param(address)].join('/')
112
+ else
113
+ param_str = param_hash.map{|k,v| [k.to_s, escape_param(v)].join('=')}.join('&')
114
+ request_path = [[base, escape_param(address)].join('/'), param_str].join('?')
115
+ end
116
+ http.start do
117
+ request = Net::HTTP::Get.new(request_path)
118
+ request.basic_auth @username, @password
119
+ response = http.request(request)
120
+ case response.code.to_i
121
+ when 200
122
+ return Leadspend::Result.new(response.body)
123
+ when 202
124
+ return Leadspend::Result.unknown(address)
125
+ when 400
126
+ raise Leadspend::Exceptions::BadRequestException, response.body
127
+ when 401
128
+ raise Leadspend::Exceptions::UnauthorizedRequestException, response.body
129
+ when 500
130
+ raise Leadspend::Exceptions::ServerException, response.body
131
+ when 503
132
+ raise Leadspend::Exceptions::ServerBusyException, response.body
133
+ else
134
+ raise Leadspend::Exceptions::UnknownResponseException, response.body
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,13 @@
1
+ ##
2
+ # = Leadspend Exceptions.
3
+ # The status code from the Leadspend server determines which exception is raised by the client.
4
+ module Leadspend
5
+ module Exceptions
6
+ class LeadspendException < Exception; end
7
+ class BadRequestException < LeadspendException ; end
8
+ class UnknownResponseException < LeadspendException ; end
9
+ class UnauthorizedRequestException < LeadspendException ; end
10
+ class ServerException < LeadspendException; end
11
+ class ServerBusyException < LeadspendException ; end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Leadspend
2
+ module Parser
3
+ class JSONParser
4
+ def self.encode(object)
5
+ JSON.generate(object)
6
+ end
7
+ def self.decode(string)
8
+ JSON.parse(string)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support'
2
+ module Leadspend
3
+ module Parser
4
+ class RailsParser
5
+ def self.encode(object)
6
+ ActiveSupport::JSON.encode(object)
7
+ end
8
+ def self.decode(string)
9
+ ActiveSupport::JSON.decode(string)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+
@@ -0,0 +1,14 @@
1
+ require 'yajl'
2
+ module Leadspend
3
+ module Parser
4
+ class YajlParser
5
+ def self.encode(object)
6
+ Yajl::Encoder.encode(object)
7
+ end
8
+ def self.decode(string)
9
+ Yajl::Parser.parse(string)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,89 @@
1
+ require 'json'
2
+
3
+ class Leadspend::Result
4
+ @@json_parser=nil
5
+ def initialize(json_string)
6
+ @raw = json_string
7
+ @result = self.class.decode_json(json_string)
8
+ end
9
+
10
+ def self.json_parser=(p)
11
+ @@json_parser = p
12
+ end
13
+
14
+ def raw
15
+ @raw
16
+ end
17
+
18
+ def result
19
+ @result['result']
20
+ end
21
+
22
+ Leadspend::RESULT_STATUSES.each do |status|
23
+ define_method("#{status}?") { result == status }
24
+ end
25
+
26
+ def self.method_missing(meth, *args, &block)
27
+ if Leadspend::RESULT_STATUSES.index(meth.to_s)
28
+ generate_result(meth.to_s, *args)
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def self.respond_to?(meth)
35
+ Leadspend::RESULT_STATUSES.include?(meth.to_s) || super
36
+ end
37
+
38
+ def ==(other)
39
+ other.is_a?(Leadspend::Result) and other.address == self.address and other.result == self.result
40
+ end
41
+
42
+ def address
43
+ @result['address']
44
+ end
45
+
46
+ # extended attributes
47
+
48
+ def role?
49
+ result['role']
50
+ end
51
+
52
+ def full?
53
+ undeliverable? and result['full']
54
+ end
55
+
56
+ def timeout?
57
+ unknown? and result['timeout']
58
+ end
59
+
60
+ def retry_seconds
61
+ unknown? and result['retry']
62
+ end
63
+
64
+
65
+ private
66
+ def self.generate_result(status, address, opts={})
67
+ new(encode_json({'result' => status, 'address' => address}.merge(opts)))
68
+ end
69
+
70
+ def self.decode_json(json_string)
71
+ json_parser.decode(json_string)
72
+ end
73
+
74
+ def self.encode_json(object)
75
+ json_parser.encode(object)
76
+ end
77
+
78
+ def self.json_parser
79
+ if @@json_parser.nil?
80
+ unless defined?(Leadspend::Parser::JSONParser)
81
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
82
+ end
83
+ @@json_parser = Leadspend::Parser::JSONParser
84
+ end
85
+ @@json_parser
86
+ end
87
+
88
+
89
+ end
@@ -0,0 +1,82 @@
1
+ require 'rubygems'
2
+ require 'fakeweb'
3
+ require "#{File.dirname(__FILE__)}/../../../init"
4
+ class Leadspend::Server
5
+ def initialize(opts={})
6
+ @username = opts[:username]
7
+ @password = opts[:password]
8
+ options = opts
9
+ @servers = options[:servers] || Leadspend::DEFAULT_SERVERS
10
+ @api_version = options[:version] || Leadspend::DEFAULT_VERSION
11
+ FakeWeb.allow_net_connect = false
12
+ register_all_urls
13
+ end
14
+
15
+ def unregister_all_urls
16
+ FakeWeb.clean_registry
17
+ end
18
+
19
+ def register_all_urls
20
+ @servers.each do |server|
21
+ Leadspend::RESULT_STATUSES.each do |status|
22
+
23
+ http_status = [200, 'OK']
24
+ email = "#{status}-#{http_status.first}@example.com"
25
+ #$stderr.puts("Registering #{url_for(server, email)}")
26
+ FakeWeb.register_uri(:get, url_for(server, email),
27
+ :body => Leadspend::Result.send(status, email).raw,
28
+ :status => http_status)
29
+ [Leadspend::MIN_TIMEOUT, Leadspend::MAX_TIMEOUT, (Leadspend::MIN_TIMEOUT-1), (Leadspend::MAX_TIMEOUT+1)].each do |timeout|
30
+ #$stderr.puts("Registering #{url_for(server, email, :timeout => timeout)}")
31
+ FakeWeb.register_uri(:get, url_for(server, email, :timeout => timeout),
32
+ :body => Leadspend::Result.send(status, email).raw,
33
+ :status => http_status)
34
+ end
35
+
36
+ # non-200 statuses
37
+
38
+ # for 202, have it be "unknown".
39
+ http_status = [202, 'Accepted']
40
+ email = "#{status}-#{http_status.first}@example.com"
41
+ FakeWeb.register_uri(:get, url_for(server, email),
42
+ :body => Leadspend::Result.unknown(email).raw,
43
+ :status => http_status)
44
+
45
+
46
+ # 401 and 400 should cause the client to raise an exception
47
+ [[400, 'Bad Request'], [401, 'Unauthorized']].each do |http_status|
48
+ email = "verified-#{http_status.first}@example.com"
49
+ FakeWeb.register_uri(:get, url_for(server, email), :body => 'Error!', :status => http_status)
50
+ end
51
+ end
52
+ end
53
+
54
+ # for 500 and 503, make this work on secondary, but not primary-- this means we can test failover
55
+ [[500, 'Internal Server Error'],[503, 'Service Unavailable']].each do |http_status|
56
+ email = "verified-#{http_status.first}@example.com"
57
+ FakeWeb.register_uri(:get, url_for(@servers.first, email), :body => 'Error!', :status => http_status)
58
+ new_http_status = [200, 'OK']
59
+ FakeWeb.register_uri(:get, url_for(@servers.last, email),
60
+ :body => Leadspend::Result.verified(email).raw,
61
+ :status => new_http_status )
62
+
63
+ # also register an "alwaysfail" address to see that the proper exception is raised
64
+ email = "alwaysfail-#{http_status.first}@example.com"
65
+ @servers.each do |server|
66
+ FakeWeb.register_uri(:get, url_for(server, email), :body => 'Error!', :status => http_status)
67
+ end
68
+ end
69
+ end
70
+
71
+ def url_for(server, email, opts={})
72
+ opts_str = ''
73
+ unless opts.empty?
74
+ opts_str += '?' + opts.map { |k,v| "#{k.to_s}=#{escape_param(v)}"}.join('&')
75
+ end
76
+ "https://#{@username}:#{@password}@#{server}/#{@api_version}/validity/#{escape_param email}#{opts_str}"
77
+ end
78
+
79
+ def escape_param(param)
80
+ URI::escape(param.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
81
+ end
82
+ end
@@ -0,0 +1,100 @@
1
+ require "#{File.dirname(__FILE__)}/../mocks/leadspend/server"
2
+ require 'test/unit'
3
+ class Leadspend::TestLeadspendClient < Test::Unit::TestCase
4
+ def setup
5
+ @server = Leadspend::Server.new(:username => 'test', :password => 'test')
6
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test')
7
+ end
8
+
9
+ def test_yajl_backend
10
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test', :json_parser => 'yajl')
11
+ verified_email="verified-200@example.com"
12
+ unknown_email="unknown-200@example.com"
13
+ assert @client.validate(verified_email)
14
+ assert @client.validate(unknown_email)
15
+ end
16
+
17
+ def test_rails_backend
18
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test', :json_parser => 'rails')
19
+ verified_email="verified-200@example.com"
20
+ unknown_email="unknown-200@example.com"
21
+ assert @client.validate(verified_email)
22
+ assert @client.validate(unknown_email)
23
+ end
24
+
25
+ def test_result_consistency
26
+ verified_email="verified-200@example.com"
27
+ unknown_email="unknown-200@example.com"
28
+ assert Leadspend::Result.verified(verified_email).verified?
29
+ assert Leadspend::Result.unknown(unknown_email).unknown?
30
+ end
31
+
32
+ def test_validate
33
+ verified_email="verified-200@example.com"
34
+ unknown_email="unknown-200@example.com"
35
+ assert @client.validate(verified_email)
36
+ assert @client.validate(unknown_email)
37
+ end
38
+
39
+ def test_ok_results
40
+ Leadspend::RESULT_STATUSES.each do |status|
41
+ email = "#{status}-200@example.com"
42
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
43
+ end
44
+ end
45
+
46
+ def test_accepted_results
47
+ Leadspend::RESULT_STATUSES.each do |status|
48
+ email = "#{status}-202@example.com"
49
+ assert_equal Leadspend::Result.unknown(email), @client.fetch_result(email)
50
+ end
51
+ end
52
+
53
+ def test_400_results
54
+ status='verified'
55
+ email = "#{status}-400@example.com"
56
+ assert_raise(Leadspend::Exceptions::BadRequestException) do
57
+ @client.fetch_result(email)
58
+ end
59
+ end
60
+
61
+ def test_401_results
62
+ status='verified'
63
+ email = "#{status}-401@example.com"
64
+ assert_raise(Leadspend::Exceptions::UnauthorizedRequestException) do
65
+ @client.fetch_result(email)
66
+ end
67
+ end
68
+
69
+ def test_500_failover_results
70
+ status='verified'
71
+ email = "#{status}-500@example.com"
72
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
73
+ end
74
+
75
+ def test_500_everywhere
76
+ status='alwaysfail'
77
+ email = "#{status}-500@example.com"
78
+ assert_raise(Leadspend::Exceptions::ServerException) do
79
+ @client.fetch_result(email)
80
+ end
81
+ end
82
+
83
+ def test_503_failover_results
84
+ status='verified'
85
+ email = "#{status}-503@example.com"
86
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
87
+ end
88
+
89
+ def test_503_everywhere
90
+ status='alwaysfail'
91
+ email = "#{status}-503@example.com"
92
+ assert_raise(Leadspend::Exceptions::ServerBusyException) do
93
+ @client.fetch_result(email)
94
+ end
95
+ end
96
+
97
+ def teardown
98
+ @server.unregister_all_urls unless @server.nil?
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leadspend
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 2
10
+ version: 1.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Justin Dossey
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain:
17
+ - |
18
+ -----BEGIN CERTIFICATE-----
19
+ MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANqYmQx
20
+ GTAXBgoJkiaJk/IsZAEZFglwb2RvbWF0aWMxEzARBgoJkiaJk/IsZAEZFgNjb20w
21
+ HhcNMTIwODIzMTc1NjI2WhcNMTMwODIzMTc1NjI2WjA+MQwwCgYDVQQDDANqYmQx
22
+ GTAXBgoJkiaJk/IsZAEZFglwb2RvbWF0aWMxEzARBgoJkiaJk/IsZAEZFgNjb20w
23
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5RGjRB6bqQgjXJJGqgsnP
24
+ o+eYygOuuJiteU8x5KEAj9VgM7GdOkBszpwDxRfBuZo8yrCmtDowD+yvTdNochOD
25
+ PTXcDaEshBsRr8j8ZW8LKUE8uFwwHGH1eeUSIzt2DytosC/MAvUbDQCD/2aqWshW
26
+ wvO2I08bSRyusrxAGILYcB3CWx0WTU/Gr5aVBaHBRRi3Ebmu2pFzRYQuDnJx7Xiq
27
+ kB9yGx8cBwRqT8YEu+vRiM+2t77xXN6mVYoP4hsNafOURHCJuW3R8r5rkbq2OP+y
28
+ EDIGIUnQS7oTndT1Xw7o2czQud2+uWAl+TMCCaN3sX10c4L05i3vKiIcioiqIzON
29
+ AgMBAAGjOTA3MB0GA1UdDgQWBBTwCGTQ7oaGQqyQXzsTDrgeDwlglTALBgNVHQ8E
30
+ BAMCBLAwCQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQo4JD6kU2Jf2+Qk0
31
+ 1/bcV1i/x2W/NBY0U3GGMg9hpVZ0U5iUM3hyEfH6fFI36qL+SeQN3OZWefdoKT1W
32
+ B9deFyS4nG4u3KX5I8StJDN1TVm/6pd2oFadkhBeOJohiYspa5XjTxdn47zZOTIU
33
+ LI+e36qne3wsTZRNw3xtp3cHgXSOKvAW8GVmJHk/2fvvzP3M14xjLSecu9gz3leB
34
+ CCypHKDQ9StNcMuvHsRyFOoojb2iJygucIcOXBy0bQEOzUVFDzwaLYNAciAUlOPs
35
+ es1G1v2drcgWtxkPCQNzgqw2rOq6B5UHqxBh9IB3xEXZ1YYaU4Si6jDLtEWy76Fa
36
+ DHOLCQ==
37
+ -----END CERTIFICATE-----
38
+
39
+ date: 2012-08-23 00:00:00 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ prerelease: false
44
+ requirement: &id001 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ hash: 19
50
+ segments:
51
+ - 3
52
+ - 10
53
+ version: "3.10"
54
+ type: :development
55
+ version_requirements: *id001
56
+ - !ruby/object:Gem::Dependency
57
+ name: hoe
58
+ prerelease: false
59
+ requirement: &id002 !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ~>
63
+ - !ruby/object:Gem::Version
64
+ hash: 7
65
+ segments:
66
+ - 3
67
+ - 0
68
+ version: "3.0"
69
+ type: :development
70
+ version_requirements: *id002
71
+ description: Leadspend client access library.
72
+ email:
73
+ - jbd@podomatic.com
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - History.txt
80
+ - Manifest.txt
81
+ - README.txt
82
+ files:
83
+ - .autotest
84
+ - History.txt
85
+ - Manifest.txt
86
+ - README.txt
87
+ - Rakefile
88
+ - lib/leadspend.rb
89
+ - lib/leadspend/exceptions.rb
90
+ - lib/leadspend/result.rb
91
+ - lib/leadspend/client.rb
92
+ - lib/leadspend/parser/json_parser.rb
93
+ - lib/leadspend/parser/yajl_parser.rb
94
+ - lib/leadspend/parser/rails_parser.rb
95
+ - test/unit/test_leadspend_client.rb
96
+ - test/mocks/leadspend/server.rb
97
+ - .gemtest
98
+ homepage: http://www.github.com/justindossey/leadspend
99
+ licenses: []
100
+
101
+ post_install_message:
102
+ rdoc_options:
103
+ - --main
104
+ - README.txt
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ requirements: []
126
+
127
+ rubyforge_project: leadspend
128
+ rubygems_version: 1.8.15
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Leadspend client access library.
132
+ test_files:
133
+ - test/unit/test_leadspend_client.rb
@@ -0,0 +1,4 @@
1
+
2
+ �:��o�����"�ݎ)��U���F���$�i
3
+ �TR�|9�b�$,_lpc�.��ѴY�Z,yn���R�.r�+� ��N�>D��5B��#JIGr���%Ͷ'�9��۲��0���_j�El����?H���Hn9$��@�+�l+^���^���8���^CG�45R[�*�>�sη��9j�-�,�f�� G-�O�|7O
4
+ ҄��5�p�*�a�*�gp� K��1ƳW7$)�c��v��&&�ʏ�,R%nv�