i_contact 0.1.0

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.
@@ -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
+