i_contact 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .env
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm use 1.9.3@i_contact --create
2
+
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in icontact.gemspec
4
+ group 'development' do
5
+ gem 'guard'
6
+ gem 'guard-rspec'
7
+ gem 'pry'
8
+ end
9
+
10
+ gemspec
11
+
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dan Pickett
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.
@@ -0,0 +1,28 @@
1
+ # Icontact
2
+
3
+ [![Build Status](https://secure.travis-ci.org/LaunchWare/icontact.png)](http://travis-ci.org/LaunchWare/icontact)
4
+
5
+ Web Wrapper for the IContact API
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'icontact'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install icontact
20
+
21
+ ## Contributing
22
+
23
+ 1. Fork it
24
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
25
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
26
+ 4. Push to the branch (`git push origin my-new-feature`)
27
+ 5. Create new Pull Request
28
+
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ end
10
+
11
+ task default: :spec
12
+
13
+ rescue LoadError
14
+ puts "RSpec is not installed"
15
+ end
@@ -0,0 +1,16 @@
1
+ export WORKING_DIR=~/work/i_contact
2
+ cd $WORKING_DIR; mvim; gitx
3
+ tmux set-option -tIContact default-path $WORKING_DIR
4
+
5
+ tmux start-server
6
+ tmux new-session -d -s IContact -n work
7
+
8
+ tmux new-window -tIContact:1 -n server
9
+ tmux new-window -tIContact:2 -n guard
10
+
11
+ tmux send-keys -tIContact:1 'ruby script/server' C-m
12
+ tmux send-keys -tIContact:2 'source .env && bundle exec guard' C-m
13
+
14
+ tmux select-window -tIContact:0
15
+ tmux attach-session -d -tIContact
16
+
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/i_contact/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Dan Pickett']
6
+ gem.email = ['dpickett@enlightsolutions.com']
7
+ gem.description = %q{web wrapper for icontact}
8
+ gem.summary = %q{web wrapper for icontact}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = 'i_contact'
15
+ gem.require_paths = ['lib']
16
+ gem.version = IContact::VERSION
17
+
18
+ gem.add_dependency 'faraday'
19
+ gem.add_dependency 'faraday_middleware'
20
+ gem.add_dependency 'activemodel'
21
+ gem.add_dependency 'active_attr'
22
+ gem.add_dependency 'multi_json'
23
+
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'mocha'
26
+ gem.add_development_dependency 'rake'
27
+ gem.add_development_dependency 'guard-rspec'
28
+ gem.add_development_dependency 'vcr'
29
+ gem.add_development_dependency 'webmock'
30
+ gem.add_development_dependency 'pry'
31
+ end
32
+
@@ -0,0 +1,87 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware/response/parse_json'
3
+ require 'faraday/request/url_encoded'
4
+
5
+ require 'active_attr'
6
+
7
+ require 'i_contact/version'
8
+ require 'i_contact/configuration'
9
+ require 'i_contact/response'
10
+
11
+ require 'i_contact/model'
12
+
13
+ require 'i_contact/account'
14
+ require 'i_contact/client_folder'
15
+
16
+ require 'i_contact/contact'
17
+ require 'i_contact/list'
18
+ require 'i_contact/subscription'
19
+
20
+ module IContact
21
+ class InvalidConfiguration < Exception; end;
22
+ class ApiError < Exception; end;
23
+ class InvalidResource < Exception; end;
24
+
25
+ class << self
26
+ def configure(&block)
27
+ @configuration = IContact::Configuration.new(&block) if block_given?
28
+ end
29
+
30
+ def configuration
31
+ @configuration
32
+ end
33
+
34
+ def configuration=(configuration)
35
+ @configuration = configuration
36
+ end
37
+
38
+ def connection
39
+ if configuration.nil? || !configuration.valid?
40
+ raise InvalidConfiguration
41
+ end
42
+
43
+ @connection ||= Faraday::Connection.new({
44
+ :headers => headers,
45
+ :ssl => {:verify => true}}) do |builder|
46
+
47
+ #builder.use Faraday::Request::UrlEncoded
48
+ builder.adapter Faraday.default_adapter
49
+ end
50
+ end
51
+
52
+ def reset_connection!
53
+ @connection = nil
54
+ connection
55
+ end
56
+
57
+ def url(with_account_and_folder = true)
58
+ base_url = "https://#{host}/icp/"
59
+ if with_account_and_folder
60
+ base_url += "a/#{configuration.account_id}/c/#{configuration.client_folder_id}/"
61
+ end
62
+ base_url
63
+
64
+ end
65
+
66
+ protected
67
+ def host
68
+ if configuration.mode == :sandbox
69
+ 'app.sandbox.icontact.com'
70
+ else
71
+ "app.icontact.com"
72
+ end
73
+ end
74
+
75
+ def headers
76
+ {
77
+ 'API-AppId' => configuration.app_id,
78
+ 'API-UserName' => configuration.user_name,
79
+ 'API-Password' => configuration.password,
80
+ 'API-Version' => '2.2',
81
+ 'Accept' => 'application/json',
82
+ 'Content-Type' => 'application/json'
83
+ }
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,14 @@
1
+ module IContact
2
+ class Account
3
+ include IContact::Model
4
+
5
+ key_attribute :account_id
6
+
7
+ class << self
8
+ def get
9
+ resp = connection.get("#{IContact.url(false)}a")
10
+ parse(resp)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module IContact
2
+ class ClientFolder
3
+ include IContact::Model
4
+
5
+ key_attribute :client_folder_id
6
+
7
+ class << self
8
+ def get
9
+ resp = connection.get("#{IContact.url(false)}a/#{account_id}/c")
10
+ parse(resp)
11
+ end
12
+
13
+ protected
14
+ def account_id
15
+ IContact.configuration.account_id
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module IContact
2
+ class Configuration
3
+ attr_accessor :app_id
4
+ attr_accessor :user_name
5
+ attr_accessor :password
6
+ attr_accessor :api_version
7
+ attr_accessor :mode
8
+ attr_accessor :account_id
9
+ attr_accessor :client_folder_id
10
+
11
+ REQUIRED_FIELDS = [
12
+ :app_id,
13
+ :user_name,
14
+ :password,
15
+ ]
16
+
17
+ def initialize(&block)
18
+ yield(self) if block_given?
19
+ @mode ||= :sandbox
20
+ @api_version || '2.2'
21
+ end
22
+
23
+ def valid?
24
+ REQUIRED_FIELDS.each do |field|
25
+ return false if send(field).nil? || send(field) == ''
26
+ end
27
+ true
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,32 @@
1
+ module IContact
2
+ class Contact
3
+ include IContact::Model
4
+
5
+ key_attribute :contact_id
6
+ attribute :email, :type => String
7
+ attribute :first_name, :type => String
8
+ attribute :last_name, :type => String
9
+ attribute :suffix, :type => String
10
+ attribute :street, :type => String
11
+ attribute :street2, :type => String
12
+ attribute :city, :type => String
13
+ attribute :state, :type => String
14
+ attribute :postalCode, :type => String
15
+ attribute :phone, :type => String
16
+ attribute :fax, :type => String
17
+ attribute :business, :type => String
18
+
19
+ def destroy
20
+ if persisted?
21
+ connection.post(path("#{self.class.resource_name.demodulize.pluralize}/#{self.attributes[self.class.key_attr.to_s]}"), {:status => 'deleted'}.to_json)
22
+ end
23
+ end
24
+
25
+ class << self
26
+ def unlisted(options = {})
27
+ parse(get({:unlisted => true}.merge(options)))
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,11 @@
1
+ module IContact
2
+ class List
3
+ include IContact::Model
4
+
5
+ key_attribute :list_id
6
+ attribute :name, :type => String
7
+ attribute :description, :type => String
8
+ attribute :publicname, :type => String
9
+ end
10
+ end
11
+
@@ -0,0 +1,138 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/class/attribute.rb'
3
+ require 'active_support/core_ext/object/blank.rb'
4
+
5
+ module IContact
6
+ module Model
7
+ extend ActiveSupport::Concern
8
+ extend ActiveModel::Naming
9
+
10
+ included do
11
+ include ActiveModel::Conversion
12
+ include ActiveModel::Validations
13
+ include ActiveAttr::TypecastedAttributes
14
+ include ActiveAttr::MassAssignment
15
+
16
+ class_attribute :key_attr
17
+ class_attribute :resource_name_attr
18
+ end
19
+
20
+ module ClassMethods
21
+ def key_attribute(key, type = Integer)
22
+ self.key_attr = key
23
+ attribute key, :type => type
24
+ end
25
+
26
+ def resource_name(name)
27
+ self.resource_name_attr = name
28
+ end
29
+
30
+ def resource_name
31
+ self.resource_name_attr || name.demodulize.downcase
32
+ end
33
+
34
+ def connection
35
+ IContact.connection
36
+ end
37
+
38
+ def path(suffix)
39
+ "#{IContact.url}#{suffix}"
40
+ end
41
+
42
+ def get(additional_args = {})
43
+ connection.get path(self.resource_name.pluralize),
44
+ additional_args
45
+ end
46
+
47
+ def parse(resp)
48
+ resp = IContact::Response.new(resp)
49
+ if !resp.valid?
50
+ else
51
+ if resource_resp = resp.parsed_response[resource_name.pluralize]
52
+ if resource_resp.kind_of?(Array)
53
+ resource_resp.inject([]) do |arr, attribute_hash|
54
+ arr << new(deserialize_attributes(attribute_hash))
55
+ arr
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def deserialize_attributes(attribute_hash)
63
+ attribute_hash.inject({}) do |hsh, key_pair|
64
+ hsh[key_pair[0].underscore] = key_pair[1]
65
+ hsh
66
+ end
67
+ end
68
+ end #end ClassMethods
69
+
70
+ def save
71
+ if valid?
72
+ if !persisted?
73
+ raw_resp = connection.post(path(self.class.resource_name.demodulize.pluralize),
74
+ serialized_attributes.to_json)
75
+ response = IContact::Response.new(raw_resp)
76
+ if response.valid? && response.warnings.empty?
77
+ if response.parsed_response.values.first && response.parsed_response.values.first.first
78
+ self.attributes = normalize_attrs(response.parsed_response.values.first.first)
79
+ end
80
+ true
81
+ else
82
+ @errors = response.errors + response.warnings
83
+ false
84
+ end
85
+ else
86
+
87
+ end
88
+ end
89
+ end
90
+
91
+ def normalize_attrs(attrs)
92
+ attrs.inject({}) do |hsh, pair|
93
+ hsh[pair[0].underscore] = pair[1]
94
+ hsh
95
+ end
96
+ end
97
+
98
+ def save!
99
+ unless save
100
+ raise IContact::InvalidResource, @errors.join(', ')
101
+ end
102
+ self
103
+ end
104
+
105
+ def destroy
106
+ if persisted?
107
+ connection.delete(path("#{self.class.resource_name.demodulize.pluralize}/#{self.attributes[self.class.key_attr.to_s]}"))
108
+ end
109
+ end
110
+
111
+ def serialized_attributes
112
+ result = attributes.inject({}) do |hsh, keypair|
113
+ hsh[keypair[0].camelcase(:lower)] = keypair[1] unless keypair[1].nil?
114
+ hsh
115
+ end
116
+
117
+ if !persisted?
118
+ [result]
119
+ else
120
+ result
121
+ end
122
+ end
123
+
124
+ def persisted?
125
+ self.class.key_attr && self.attributes[self.class.key_attr.to_s].present?
126
+ end
127
+
128
+ protected
129
+ def path(suffix)
130
+ self.class.path(suffix)
131
+ end
132
+
133
+ def connection
134
+ self.class.connection
135
+ end
136
+ end
137
+ end
138
+