perfect_reach 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 +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +8 -0
- data/config.yml +8 -0
- data/lib/perfect_reach.rb +18 -0
- data/lib/perfect_reach/api.rb +35 -0
- data/lib/perfect_reach/api_error.rb +19 -0
- data/lib/perfect_reach/api_request.rb +66 -0
- data/lib/perfect_reach/configuration.rb +14 -0
- data/lib/perfect_reach/contact.rb +17 -0
- data/lib/perfect_reach/contact_list.rb +66 -0
- data/lib/perfect_reach/version.rb +3 -0
- data/perfect_reach.gemspec +29 -0
- data/test/minitest_helper.rb +19 -0
- data/test/perfect_reach/api_request_test.rb +43 -0
- data/test/perfect_reach/api_test.rb +12 -0
- data/test/perfect_reach/contact_list_test.rb +73 -0
- data/test/perfect_reach/contact_test.rb +20 -0
- data/test/perfect_reach_test.rb +17 -0
- metadata +207 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mike Petersen
|
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,37 @@
|
|
1
|
+
# PerfectReach
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'PerfectReach'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install PerfectReach
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
Configuration:
|
24
|
+
PerfectReach.configure do |config|
|
25
|
+
config.api_key = 'YOUR_API_KEY'
|
26
|
+
config.host = api.perfect-reach.com
|
27
|
+
config.port = 443
|
28
|
+
config.use_https = true
|
29
|
+
end
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/config.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require "perfect_reach/version"
|
3
|
+
require "perfect_reach/api"
|
4
|
+
require "perfect_reach/api_error"
|
5
|
+
require "perfect_reach/api_request"
|
6
|
+
require "perfect_reach/configuration"
|
7
|
+
require "perfect_reach/contact"
|
8
|
+
require "perfect_reach/contact_list"
|
9
|
+
|
10
|
+
module PerfectReach
|
11
|
+
def self.configure
|
12
|
+
yield PerfectReach::Configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.config
|
16
|
+
PerfectReach::Configuration
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PerfectReach
|
2
|
+
class Api
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def initialize(api_key = PerfectReach.config.api_key)
|
6
|
+
@api_key = api_key
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method_name, *args, &block)
|
10
|
+
params, request_type = args
|
11
|
+
request = ApiRequest.new(method_name, params, request_type, @api_key)
|
12
|
+
request.response
|
13
|
+
end
|
14
|
+
|
15
|
+
def get(method_name, params)
|
16
|
+
request = ApiRequest.new(method_name, params, 'get', @api_key)
|
17
|
+
request.response
|
18
|
+
end
|
19
|
+
|
20
|
+
def post(method_name, params)
|
21
|
+
request = ApiRequest.new(method_name, params, 'post', @api_key)
|
22
|
+
request.response
|
23
|
+
end
|
24
|
+
|
25
|
+
def put(method_name, params)
|
26
|
+
request = ApiRequest.new(method_name, params, 'put', @api_key)
|
27
|
+
request.response
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(method_name, params)
|
31
|
+
request = ApiRequest.new(method_name, params, 'delete', @api_key)
|
32
|
+
request.response
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
module PerfectReach
|
5
|
+
class ApiError < StandardError
|
6
|
+
def initialize(code, res, request, request_path, params)
|
7
|
+
# code is ugly, output is pretty
|
8
|
+
super("error #{code} while sending #{request.inspect} to #{request_path} with #{params.inspect}\n\n" +
|
9
|
+
(res['errors'].present? ?
|
10
|
+
[(res['errors'] || [])].flatten.map do |param, text|
|
11
|
+
[param, text].map(&:to_s).reject(&:blank?).join(': ')
|
12
|
+
end.join("\n") :
|
13
|
+
res.inspect
|
14
|
+
) +
|
15
|
+
"\n\nPlease see http://api.perfect-reach.com for more informations on error numbers.\n\n"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
require 'net/http'
|
4
|
+
require "net/https"
|
5
|
+
require 'json'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
module PerfectReach
|
9
|
+
class ApiRequest
|
10
|
+
def initialize(method_name, params = {}, request_type = nil, auth_token = PerfectReach.config.api_key, host = PerfectReach.config.host, port = PerfectReach.config.port)
|
11
|
+
@method_name = method_name.to_s
|
12
|
+
@params = (params || {}).merge(:format => 'json')
|
13
|
+
@request_type = (request_type || guess_request_type).camelize
|
14
|
+
@auth_token = auth_token
|
15
|
+
@host = host
|
16
|
+
@port = port
|
17
|
+
end
|
18
|
+
|
19
|
+
def response
|
20
|
+
@response ||= begin
|
21
|
+
http = Net::HTTP.new(@host, @port)
|
22
|
+
http.use_ssl = PerfectReach.config.use_https
|
23
|
+
res = http.request(request)
|
24
|
+
|
25
|
+
case res
|
26
|
+
when Net::HTTPSuccess
|
27
|
+
JSON.parse(res.body || '{}')
|
28
|
+
when Net::HTTPNotModified
|
29
|
+
{"status" => "not_modified"}
|
30
|
+
else
|
31
|
+
raise ApiError.new(res.code, JSON.parse(res.body.presence || '{}'), request, request_path, @params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def request
|
38
|
+
@request ||= begin
|
39
|
+
req = "Net::HTTP::#{@request_type}".constantize.new(request_path)
|
40
|
+
Net::HTTP::Get
|
41
|
+
req.add_field 'Authorization', "Token token=\"#{@auth_token}\""
|
42
|
+
req.add_field 'X-Api-Version', PerfectReach.config.api_version
|
43
|
+
req.set_form_data(@params)
|
44
|
+
req
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_path
|
49
|
+
@request_path ||= begin
|
50
|
+
path = "/api/#{@method_name}"
|
51
|
+
if @request_type == 'Get'
|
52
|
+
path << '?' + @params.collect { |k, v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&')
|
53
|
+
end
|
54
|
+
path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def guess_request_type
|
59
|
+
if @method_name =~ /(?:Create|Add|Remove|Delete|Update)(?:[A-Z]|$)/
|
60
|
+
'Post'
|
61
|
+
else
|
62
|
+
'Get'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
|
3
|
+
module PerfectReach
|
4
|
+
module Configuration
|
5
|
+
mattr_accessor :api_version
|
6
|
+
mattr_accessor :api_key
|
7
|
+
mattr_accessor :host
|
8
|
+
mattr_accessor :port
|
9
|
+
mattr_accessor :use_https
|
10
|
+
|
11
|
+
@@api_version = 0.1
|
12
|
+
@@use_https = true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'perfect_reach/api'
|
2
|
+
|
3
|
+
module PerfectReach
|
4
|
+
class Contact < OpenStruct
|
5
|
+
def infos(options = {})
|
6
|
+
PerfectReach::Api.instance.get("contacts/#{(self.id || self.email)}", options)["contact"]
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def all(options = {})
|
11
|
+
PerfectReach::Api.instance.get('contacts', options)["contacts"].map do |result_hash|
|
12
|
+
self.new(result_hash)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'perfect_reach/api'
|
2
|
+
require 'perfect_reach/contact'
|
3
|
+
|
4
|
+
module PerfectReach
|
5
|
+
class ContactList < OpenStruct
|
6
|
+
def update(options = {})
|
7
|
+
PerfectReach::Api.instance.put("contact_lists/#{self.id}", options)["status"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_contacts(contacts, options={})
|
11
|
+
throw 'Contacts must be an Array' unless contacts.is_a? Array
|
12
|
+
contact_data = []
|
13
|
+
contacts.each do |p|
|
14
|
+
contact_data << (p.is_a?(PerfectReach::Contact) ? {email: p.email.to_s, name: p.name.to_s} : p)
|
15
|
+
end
|
16
|
+
PerfectReach::Api.instance.post("contact_lists/#{self.id}/add_contacts", options.reverse_merge(:contacts => contacts.to_json))["status"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def unsubscribe_contact(*params)
|
20
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
21
|
+
contact = params.map { |p| p.is_a?(PerfectReach::Contact) ? p.email.to_s : p.to_s }.reject(&:blank?).first
|
22
|
+
PerfectReach::Api.instance.post("contact_lists/#{self.id}/unsubscribe_contact", options.reverse_merge(:contact => contact))["status"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_contacts(contacts, options={})
|
26
|
+
throw 'Contacts must be an Array' unless contacts.is_a? Array
|
27
|
+
contact_data = []
|
28
|
+
contacts.each do |p|
|
29
|
+
contact_data << (p.is_a?(PerfectReach::Contact) ? {email: p.email.to_s, name: p.name.to_s} : p)
|
30
|
+
end
|
31
|
+
PerfectReach::Api.instance.delete("contact_lists/#{self.id}/remove_contacts", options.reverse_merge(:contacts => contacts.to_json))["status"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def contacts(options = {})
|
35
|
+
PerfectReach::Api.instance.get("contact_lists/#{self.id}/contacts", options)["contacts"].map do |contact|
|
36
|
+
PerfectReach::Contact.new(contact)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def email(options = {})
|
41
|
+
PerfectReach::Api.instance.get("contact_lists/#{self.id}/email", options)["email"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def statistics(options = {})
|
45
|
+
PerfectReach::Api.instance.get("contact_lists/#{self.id}/statistics", options)["statistics"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(options = {})
|
49
|
+
PerfectReach::Api.instance.delete("contact_lists/#{self.id}", options)["status"]
|
50
|
+
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
def create(options = {})
|
54
|
+
data = PerfectReach::Api.instance.post('contact_lists', options)
|
55
|
+
throw data['error_msg'] unless 'ok'.eql? data['status']
|
56
|
+
self.new(options.merge(:id => data["id"].to_s))
|
57
|
+
end
|
58
|
+
|
59
|
+
def all(options = {})
|
60
|
+
(PerfectReach::Api.instance.get('contact_lists', options)["contact_lists"] || []).map do |result_hash|
|
61
|
+
self.new(result_hash)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'perfect_reach/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "perfect_reach"
|
8
|
+
spec.version = PerfectReach::VERSION
|
9
|
+
spec.authors = ["Mike Petersen"]
|
10
|
+
spec.email = ["mike@odania-it.de"]
|
11
|
+
spec.description = %q{Manage Ads, ContactLists via an api}
|
12
|
+
spec.summary = %q{Manage Ads, ContactLists via an api}
|
13
|
+
spec.homepage = "http://www.perfect-reach.com/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport", ">= 3.1.0"
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
spec.add_development_dependency "minitest-matchers"
|
26
|
+
spec.add_development_dependency "turn"
|
27
|
+
spec.add_development_dependency "json"
|
28
|
+
spec.add_development_dependency "mocha"
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'perfect_reach'
|
4
|
+
|
5
|
+
test_account = YAML::load(File.new(File.expand_path("../../config.yml", __FILE__)))['perfect_reach']
|
6
|
+
|
7
|
+
MiniTest::Spec.before do
|
8
|
+
PerfectReach.configure do |config|
|
9
|
+
config.api_key = test_account['api_key']
|
10
|
+
config.host = test_account['host']
|
11
|
+
config.port = test_account['port']
|
12
|
+
config.use_https = test_account['use_https']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
MiniTest::Spec.after do
|
17
|
+
Object.send(:remove_const, 'PerfectReach')
|
18
|
+
Dir["#{File.dirname(__FILE__)}/../lib/**/*.rb"].each { |f| load f }
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'minitest_helper'
|
4
|
+
|
5
|
+
describe PerfectReach::ApiRequest do
|
6
|
+
|
7
|
+
describe "#request_path" do
|
8
|
+
it "should return the path of the method" do
|
9
|
+
PerfectReach::ApiRequest.new('method_name').send(:request_path).must_equal '/api/method_name?format=json'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should respect api_version" do
|
13
|
+
PerfectReach.config.expects(:api_version).returns('0.2')
|
14
|
+
PerfectReach::ApiRequest.new('method_name').send(:request).get_fields('X-Api-Version')[0].must_equal '0.2'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#request" do
|
19
|
+
it "should return an Http request" do
|
20
|
+
request = PerfectReach::ApiRequest.new('method_name', {}, 'Post')
|
21
|
+
request.send(:request).must_be_kind_of(Net::HTTP::Post)
|
22
|
+
|
23
|
+
request = PerfectReach::ApiRequest.new('method_name', {}, 'Get')
|
24
|
+
request.send(:request).must_be_kind_of(Net::HTTP::Get)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#response" do
|
29
|
+
it "should raise an ApiError if authentication fails" do
|
30
|
+
request = PerfectReach::ApiRequest.new('method_name', {}, 'Get')
|
31
|
+
lambda {
|
32
|
+
request.response
|
33
|
+
}.must_raise(PerfectReach::ApiError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return a Hash with response values if request is ok" do
|
37
|
+
request = PerfectReach::ApiRequest.new('me', {}, 'Get')
|
38
|
+
response = request.response
|
39
|
+
response.must_be_kind_of(Hash)
|
40
|
+
response['user']['email'].must_equal 'test@perfect-reach.com'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'minitest_helper'
|
3
|
+
|
4
|
+
describe PerfectReach::Api do
|
5
|
+
describe "#method_missing" do
|
6
|
+
it "should create an ApiRequest" do
|
7
|
+
request = mock(:response => true)
|
8
|
+
PerfectReach::ApiRequest.expects(:new).with(:user_infos, {:param1 => 1}, 'Post', PerfectReach.config.api_key).returns(request)
|
9
|
+
PerfectReach::Api.instance.user_infos({:param1 => 1}, 'Post')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe PerfectReach::ContactList do
|
4
|
+
it 'has an integration suite, tested directly against PerfectReach service' do
|
5
|
+
# clean-up all existing lists:
|
6
|
+
PerfectReach::ContactList.all.each do |list|
|
7
|
+
list.delete.must_equal "ok"
|
8
|
+
end
|
9
|
+
|
10
|
+
# PerfectReach::ContactList.all for no lists
|
11
|
+
PerfectReach::ContactList.all.must_be_empty
|
12
|
+
|
13
|
+
exception = proc { PerfectReach::ContactList.create(name: 'My PerfectReach list') }.must_raise(PerfectReach::ApiError)
|
14
|
+
exception.to_s.must_match /invalid_language/
|
15
|
+
|
16
|
+
# PerfectReach::ContactList#create
|
17
|
+
list = PerfectReach::ContactList.create(name: 'My PerfectReach list', sign_up_allowed: true, show_in_index: false, category_ids: nil,
|
18
|
+
title: 'My PerfectReach list', description: 'My Description', language: 'de', homepage_url: 'http://www.perfect-reach.com')
|
19
|
+
list.must_be_instance_of PerfectReach::ContactList
|
20
|
+
list.name.must_equal 'My PerfectReach list'
|
21
|
+
list.title.must_equal 'My PerfectReach list'
|
22
|
+
list.sign_up_allowed.must_equal true
|
23
|
+
list.show_in_index.must_equal false
|
24
|
+
list.description.must_equal 'My Description'
|
25
|
+
list.homepage_url.must_equal 'http://www.perfect-reach.com'
|
26
|
+
|
27
|
+
# PerfectReach::ContactList#update.
|
28
|
+
list.update(:name => 'My updated PerfectReach list', :title => "myupdatedPerfectReachlist").must_equal "ok"
|
29
|
+
updated_list = PerfectReach::ContactList.all.first
|
30
|
+
updated_list.name.must_equal 'My updated PerfectReach list'
|
31
|
+
updated_list.title.must_equal 'myupdatedPerfectReachlist'
|
32
|
+
updated_list.id.must_equal list.id
|
33
|
+
|
34
|
+
# PerfectReach::ContactList.all
|
35
|
+
lists = PerfectReach::ContactList.all
|
36
|
+
lists.count.must_equal 1
|
37
|
+
lists.first.must_be_instance_of PerfectReach::ContactList
|
38
|
+
lists.first.id.must_equal updated_list.id
|
39
|
+
|
40
|
+
# PerfectReach::ContactList#add_contacts
|
41
|
+
list.add_contacts([{email: "c1@contacts.com", name: 'c1'}]).must_equal "ok"
|
42
|
+
list.add_contacts([{email: "c1@contacts.com", name: 'c1'}]).must_equal "not_modified"
|
43
|
+
list.add_contacts([{email: "c2@contacts.com", name: 'c2'}, {email: "c3@contacts.com", name: 'c3'}]).must_equal "ok"
|
44
|
+
list.add_contacts([{email: "c4@contacts.com", name: 'c4'}, {email: "c5@contacts.com", name: 'c5'}]).must_equal "ok"
|
45
|
+
|
46
|
+
# PerfectReach::ContactList#contacts and validate results of add_contacts
|
47
|
+
contacts = list.contacts
|
48
|
+
contacts.first.must_be_instance_of PerfectReach::Contact
|
49
|
+
contacts.map(&:email).sort.must_equal ["c1@contacts.com", "c2@contacts.com", "c3@contacts.com", "c4@contacts.com", "c5@contacts.com"]
|
50
|
+
|
51
|
+
# PerfectReach::ContactList#unsubscribe_contact
|
52
|
+
list.unsubscribe_contact("c1@contacts.com").must_equal "ok"
|
53
|
+
exception = proc { list.unsubscribe_contact("c1@contacts.com") }.must_raise(PerfectReach::ApiError)
|
54
|
+
exception.to_s.must_match /already_unsubscribed/
|
55
|
+
|
56
|
+
# PerfectReach::ContactList#remove_contacts
|
57
|
+
list.remove_contacts([{email: "does-not-exist@nowhere.com"}]).must_equal "not_modified"
|
58
|
+
list.remove_contacts([{email: "c1@contacts.com"}, {email: "c2@contacts.com"}]).must_equal "ok"
|
59
|
+
list.contacts.count.must_equal 3
|
60
|
+
|
61
|
+
# PerfectReach::ContactList#email
|
62
|
+
list.email.must_match /\@lists\.perfect-reach\.com$/
|
63
|
+
|
64
|
+
# PerfectReach::ContactList#statistics
|
65
|
+
list.statistics["sent"].must_equal 0
|
66
|
+
|
67
|
+
# PerfectReach::ContactList#delete
|
68
|
+
list.delete.must_equal 'ok'
|
69
|
+
PerfectReach::ContactList.all.must_be_empty
|
70
|
+
exception = proc { list.delete }.must_raise(PerfectReach::ApiError)
|
71
|
+
exception.to_s.must_match /invalid_id/
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe PerfectReach::Contact do
|
4
|
+
it 'has an integration suite, tested directly against PerfectReach service' do
|
5
|
+
# init
|
6
|
+
PerfectReach::ContactList.all.each do |list|
|
7
|
+
list.delete
|
8
|
+
end
|
9
|
+
list = PerfectReach::ContactList.create(:name => 'My PerfectReach list', language: 'en')
|
10
|
+
list.add_contacts([{email: "c1@contacts.com"}])
|
11
|
+
|
12
|
+
# PerfectReach::Contact.all
|
13
|
+
contacts = PerfectReach::Contact.all
|
14
|
+
contacts.wont_be_empty # we can't empty the whole contact list...
|
15
|
+
contacts.first.must_be_instance_of PerfectReach::Contact
|
16
|
+
|
17
|
+
# PerfectReach::Contact#infos
|
18
|
+
contacts.first.infos["mails_clicked"].wont_be_nil
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe PerfectReach do
|
4
|
+
describe "#configure" do
|
5
|
+
it "should permit to set api keys and remember them" do
|
6
|
+
PerfectReach.configure do |config|
|
7
|
+
config.api_key = 'sad786523'
|
8
|
+
config.host = 'test.perfect-reach.com'
|
9
|
+
config.port = '1324'
|
10
|
+
end
|
11
|
+
|
12
|
+
PerfectReach.config.api_key.must_equal 'sad786523'
|
13
|
+
PerfectReach.config.host.must_equal 'test.perfect-reach.com'
|
14
|
+
PerfectReach.config.port.must_equal '1324'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: perfect_reach
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Petersen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.1.0
|
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: 3.1.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: minitest-matchers
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: turn
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: json
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: mocha
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
description: Manage Ads, ContactLists via an api
|
143
|
+
email:
|
144
|
+
- mike@odania-it.de
|
145
|
+
executables: []
|
146
|
+
extensions: []
|
147
|
+
extra_rdoc_files: []
|
148
|
+
files:
|
149
|
+
- .gitignore
|
150
|
+
- Gemfile
|
151
|
+
- LICENSE.txt
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- config.yml
|
155
|
+
- lib/perfect_reach.rb
|
156
|
+
- lib/perfect_reach/api.rb
|
157
|
+
- lib/perfect_reach/api_error.rb
|
158
|
+
- lib/perfect_reach/api_request.rb
|
159
|
+
- lib/perfect_reach/configuration.rb
|
160
|
+
- lib/perfect_reach/contact.rb
|
161
|
+
- lib/perfect_reach/contact_list.rb
|
162
|
+
- lib/perfect_reach/version.rb
|
163
|
+
- perfect_reach.gemspec
|
164
|
+
- test/minitest_helper.rb
|
165
|
+
- test/perfect_reach/api_request_test.rb
|
166
|
+
- test/perfect_reach/api_test.rb
|
167
|
+
- test/perfect_reach/contact_list_test.rb
|
168
|
+
- test/perfect_reach/contact_test.rb
|
169
|
+
- test/perfect_reach_test.rb
|
170
|
+
homepage: http://www.perfect-reach.com/
|
171
|
+
licenses:
|
172
|
+
- MIT
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
require_paths:
|
176
|
+
- lib
|
177
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
178
|
+
none: false
|
179
|
+
requirements:
|
180
|
+
- - ! '>='
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
segments:
|
184
|
+
- 0
|
185
|
+
hash: 4411597228737958065
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
none: false
|
188
|
+
requirements:
|
189
|
+
- - ! '>='
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
segments:
|
193
|
+
- 0
|
194
|
+
hash: 4411597228737958065
|
195
|
+
requirements: []
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 1.8.25
|
198
|
+
signing_key:
|
199
|
+
specification_version: 3
|
200
|
+
summary: Manage Ads, ContactLists via an api
|
201
|
+
test_files:
|
202
|
+
- test/minitest_helper.rb
|
203
|
+
- test/perfect_reach/api_request_test.rb
|
204
|
+
- test/perfect_reach/api_test.rb
|
205
|
+
- test/perfect_reach/contact_list_test.rb
|
206
|
+
- test/perfect_reach/contact_test.rb
|
207
|
+
- test/perfect_reach_test.rb
|