contactually-ruby 0.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.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +7 -0
- data/lib/contactually-ruby.rb +38 -0
- data/lib/contactually/accounts.rb +22 -0
- data/lib/contactually/api.rb +87 -0
- data/lib/contactually/buckets.rb +49 -0
- data/lib/contactually/contact_groupings.rb +16 -0
- data/lib/contactually/contacts.rb +54 -0
- data/lib/contactually/contents.rb +30 -0
- data/lib/contactually/errors.rb +21 -0
- data/lib/contactually/groupings.rb +36 -0
- data/lib/contactually/middleware/error_detector.rb +31 -0
- data/lib/contactually/notes.rb +31 -0
- data/lib/contactually/representer/account_representer.rb +15 -0
- data/lib/contactually/representer/bucket_representer.rb +16 -0
- data/lib/contactually/representer/contact_representer.rb +48 -0
- data/lib/contactually/representer/content_representer.rb +18 -0
- data/lib/contactually/representer/grouping_representer.rb +30 -0
- data/lib/contactually/representer/grouping_statistic_representer.rb +14 -0
- data/lib/contactually/representer/note_representer.rb +15 -0
- data/lib/contactually/representer/task_representer.rb +21 -0
- data/lib/contactually/tasks.rb +49 -0
- data/lib/contactually/utils.rb +44 -0
- data/lib/contactually/version.rb +3 -0
- data/spec/accounts_spec.rb +58 -0
- data/spec/api_spec.rb +125 -0
- data/spec/buckets_spec.rb +97 -0
- data/spec/contact_groupings_spec.rb +44 -0
- data/spec/contacts_spec.rb +133 -0
- data/spec/contents_spec.rb +80 -0
- data/spec/error_detector_spec.rb +24 -0
- data/spec/fixtures/account.json +10 -0
- data/spec/fixtures/accounts_index.json +19 -0
- data/spec/fixtures/bucket.json +8 -0
- data/spec/fixtures/buckets_index.json +41 -0
- data/spec/fixtures/contact.json +38 -0
- data/spec/fixtures/contacts_index.json +172 -0
- data/spec/fixtures/content.json +10 -0
- data/spec/fixtures/contents_index.json +29 -0
- data/spec/fixtures/grouping.json +19 -0
- data/spec/fixtures/groupings_index.json +28 -0
- data/spec/fixtures/note.json +7 -0
- data/spec/fixtures/note_destroy.json +4 -0
- data/spec/fixtures/notes_index.json +30 -0
- data/spec/fixtures/task.json +27 -0
- data/spec/fixtures/tasks_index.json +41 -0
- data/spec/groupings_spec.rb +85 -0
- data/spec/notes_spec.rb +85 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/tasks_spec.rb +127 -0
- metadata +205 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Groupings
|
3
|
+
def initialize(master)
|
4
|
+
@master = master
|
5
|
+
end
|
6
|
+
|
7
|
+
def create(params = {})
|
8
|
+
hash = @master.call('groupings.json', :post, params)
|
9
|
+
Contactually::Utils.build_grouping(hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def index(params = {})
|
13
|
+
hash = @master.call('groupings.json', :get, params)
|
14
|
+
Contactually::Utils.groupings_hash_to_objects(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def minimal_index(params = {})
|
18
|
+
hash = @master.call('groupings/minimal_index.json', :get, params)
|
19
|
+
Contactually::Utils.build_grouping(hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy(id, params = {})
|
23
|
+
@master.call("groupings/#{id}.json", :delete, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def show(id, params = {})
|
27
|
+
hash = @master.call("groupings/#{id}.json", :get, params)
|
28
|
+
Contactually::Utils.build_grouping(hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(id, params = {})
|
32
|
+
hash = @master.call("groupings/#{id}.json", :put, params)
|
33
|
+
Contactually::Utils.build_grouping(hash)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Contactually
|
2
|
+
module Middleware
|
3
|
+
class ErrorDetector < Faraday::Middleware
|
4
|
+
|
5
|
+
def call(env)
|
6
|
+
@app.call(env).on_complete do |env|
|
7
|
+
unless (200..299).include? env[:status]
|
8
|
+
cast_error(env[:body])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def cast_error(body)
|
16
|
+
case JSON.parse(body)['error']
|
17
|
+
when /^Invalid parameters/ then
|
18
|
+
raise InvalidParametersError, body
|
19
|
+
when /^We already have/ then
|
20
|
+
raise DuplicatedContactError, body
|
21
|
+
when /^You need to sign in/ then
|
22
|
+
raise AuthenticationError, body
|
23
|
+
else
|
24
|
+
raise APIError, body
|
25
|
+
end
|
26
|
+
rescue JSON::ParserError
|
27
|
+
raise APIError, body
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Notes
|
3
|
+
def initialize(master)
|
4
|
+
@master = master
|
5
|
+
end
|
6
|
+
|
7
|
+
def index(params = {})
|
8
|
+
hash = @master.call('notes.json', :get, params)
|
9
|
+
Contactually::Utils.notes_hash_to_objects(hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def show(id, params = {})
|
13
|
+
hash = @master.call("notes/#{id}.json", :get, params)
|
14
|
+
Contactually::Utils.build_note(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(params = {})
|
18
|
+
hash = @master.call('notes.json', :post, params)
|
19
|
+
Contactually::Utils.build_note(hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy(id, params = {})
|
23
|
+
@master.call("notes/#{id}.json", :delete, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update(id, params = {})
|
27
|
+
hash = @master.call("notes/#{id}.json", :put, params)
|
28
|
+
Contactually::Utils.build_note(hash)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Account < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class AccountRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :username
|
10
|
+
property :remote_id
|
11
|
+
property :type
|
12
|
+
property :disabled_at
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Bucket < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class BucketRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :name
|
10
|
+
property :goal
|
11
|
+
property :reminder_interval
|
12
|
+
property :created_at
|
13
|
+
property :updated_at
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Contact < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class ContactRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :user_id
|
10
|
+
property :first_name
|
11
|
+
property :last_name
|
12
|
+
property :full_name
|
13
|
+
property :initials
|
14
|
+
property :title
|
15
|
+
property :company
|
16
|
+
property :email
|
17
|
+
property :avatar
|
18
|
+
property :avatar_url
|
19
|
+
property :last_contacted
|
20
|
+
property :visible
|
21
|
+
property :twitter
|
22
|
+
property :facebook_url
|
23
|
+
property :linkedin_url
|
24
|
+
property :first_contacted
|
25
|
+
property :created_at
|
26
|
+
property :updated_at
|
27
|
+
property :hits
|
28
|
+
property :team_parent_id
|
29
|
+
property :snoozed_at
|
30
|
+
property :snooze_days
|
31
|
+
property :email_addresses
|
32
|
+
property :tags
|
33
|
+
property :contact_status
|
34
|
+
property :team_last_contacted
|
35
|
+
property :team_last_contacted_by
|
36
|
+
property :phone_numbers
|
37
|
+
property :addresses
|
38
|
+
property :social_profiles
|
39
|
+
property :websites
|
40
|
+
property :custom_fields
|
41
|
+
property :sent
|
42
|
+
property :received
|
43
|
+
property :link
|
44
|
+
property :content
|
45
|
+
collection :groupings, extend: GroupingRepresenter, class: Grouping
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Content < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class ContentRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :user_id
|
10
|
+
property :url
|
11
|
+
property :title
|
12
|
+
property :description
|
13
|
+
property :article
|
14
|
+
property :original_content_id
|
15
|
+
collection :groupings, extend: GroupingRepresenter, class: Grouping
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Grouping < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class GroupingRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :type
|
10
|
+
property :name
|
11
|
+
property :stub
|
12
|
+
property :user_id
|
13
|
+
property :domain_id
|
14
|
+
property :editable
|
15
|
+
property :conversable
|
16
|
+
property :locked
|
17
|
+
property :derived_from_id
|
18
|
+
property :created_at
|
19
|
+
property :updated_at
|
20
|
+
property :has_followups
|
21
|
+
property :num_days_to_followup
|
22
|
+
property :program_id
|
23
|
+
property :objective
|
24
|
+
property :sort_order
|
25
|
+
property :accounts
|
26
|
+
property :number_of_contacts
|
27
|
+
property :goal
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Contactually
|
2
|
+
class GroupingStatistic < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class GroupingStatisticRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :messages_sent
|
9
|
+
property :messages_received
|
10
|
+
property :status
|
11
|
+
collection :contacts, extend: ContactRepresenter, class: Contact
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Note < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class NoteRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :body
|
10
|
+
property :contact_id
|
11
|
+
property :timestamp
|
12
|
+
property :user_id
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Task < OpenStruct
|
3
|
+
end
|
4
|
+
|
5
|
+
module Representer
|
6
|
+
class TaskRepresenter < Roar::Decorator
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
property :id
|
9
|
+
property :title
|
10
|
+
property :due_date
|
11
|
+
property :completed_at
|
12
|
+
property :deleted_at
|
13
|
+
property :is_follow_up
|
14
|
+
property :last_contacted
|
15
|
+
property :contact_id
|
16
|
+
property :ignored
|
17
|
+
property :completed_via
|
18
|
+
property :approval_data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Tasks
|
3
|
+
def initialize(master)
|
4
|
+
@master = master
|
5
|
+
end
|
6
|
+
|
7
|
+
def show(id, params = {})
|
8
|
+
hash = @master.call("tasks/#{id}.json", :get, params)
|
9
|
+
Contactually::Utils.build_task(hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def complete(id, params = {})
|
13
|
+
hash = @master.call("tasks/#{id}/complete.json", :post, params)
|
14
|
+
Contactually::Utils.build_task(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(params = {})
|
18
|
+
hash = @master.call('tasks.json', :post, params)
|
19
|
+
Contactually::Utils.build_task(hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy(id, params = {})
|
23
|
+
@master.call("tasks/#{id}.json", :delete, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_followups(params = {})
|
27
|
+
@master.call('tasks/generate_followups.json', :post, params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ignore(id, params = {})
|
31
|
+
hash = @master.call("tasks/#{id}/ignore.json", :post, params)
|
32
|
+
Contactually::Utils.build_task(hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
def index(params = {})
|
36
|
+
hash = @master.call('tasks.json', :get, params)
|
37
|
+
Contactually::Utils.tasks_hash_to_objects(hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
def snooze(id, params = {})
|
41
|
+
@master.call("tasks/#{id}/snooze.json", :post, params)
|
42
|
+
end
|
43
|
+
|
44
|
+
def update(id, params = {})
|
45
|
+
hash = @master.call("tasks/#{id}.json", :put, params)
|
46
|
+
Contactually::Utils.build_task(hash)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Contactually
|
2
|
+
class Utils
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def method_missing(m, *args)
|
6
|
+
case m
|
7
|
+
when /^(\w*)_hash_to_objects/ then
|
8
|
+
hash_to_objects($1, *args)
|
9
|
+
when /^build_(\w*)/ then
|
10
|
+
build_object($1, *args)
|
11
|
+
else
|
12
|
+
super(m, *args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def respond_to?(m, *args)
|
17
|
+
case m
|
18
|
+
when /^(\w*)_hash_to_objects/ then
|
19
|
+
true
|
20
|
+
when /^build_(\w*)/ then
|
21
|
+
true
|
22
|
+
else
|
23
|
+
super(m, *args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def hash_to_objects(type, hash)
|
30
|
+
representer_class = "Contactually::Representer::#{type.classify}Representer".constantize
|
31
|
+
object_class = "Contactually::#{type.classify}".constantize
|
32
|
+
hash['data'].inject([]) do |arr, obj|
|
33
|
+
arr << representer_class.new(object_class.new).from_hash(obj)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_object(type, hash)
|
38
|
+
representer_class = "Contactually::Representer::#{type.classify}Representer".constantize
|
39
|
+
object_class = "Contactually::#{type.classify}".constantize
|
40
|
+
representer_class.new(object_class.new).from_hash(hash)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Contactually::Accounts do
|
4
|
+
|
5
|
+
let(:account_json) { File.read(File.join(File.dirname(__FILE__),"fixtures/account.json")) }
|
6
|
+
let(:accounts_index_json) { File.read(File.join(File.dirname(__FILE__),"fixtures/accounts_index.json")) }
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
Contactually.configure { |c| c.access_token = 'VALID_ACCESS_TOKEN' }
|
10
|
+
@master = Contactually::API.new
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { described_class.new @master }
|
14
|
+
describe '#initialize' do
|
15
|
+
specify do
|
16
|
+
expect(subject).to be_kind_of Contactually::Accounts
|
17
|
+
end
|
18
|
+
|
19
|
+
specify do
|
20
|
+
expect(subject.instance_variable_get(:@master)).to be_kind_of Contactually::API
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#index' do
|
25
|
+
it 'calls the api with correct params' do
|
26
|
+
allow(@master).to receive(:call).with('accounts.json', :get, { foo: :bar }).and_return({ 'data' => [] })
|
27
|
+
subject.index({ foo: :bar })
|
28
|
+
expect(@master).to have_received(:call)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns accounts from json response' do
|
32
|
+
allow(@master).to receive(:call).with('accounts.json', :get, {}).and_return(JSON.load(accounts_index_json))
|
33
|
+
expect(subject.index({})).to be_kind_of Array
|
34
|
+
expect(subject.index({})[0]).to be_kind_of Contactually::Account
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#show' do
|
39
|
+
it 'calls the api with correct params' do
|
40
|
+
allow(@master).to receive(:call).with('accounts/1.json', :get, { foo: :bar }).and_return({ id: 1 })
|
41
|
+
subject.show(1, { foo: :bar })
|
42
|
+
expect(@master).to have_received(:call)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns an account' do
|
46
|
+
allow(@master).to receive(:call).with('accounts/1.json', :get, { foo: :bar }).and_return(JSON.load(account_json))
|
47
|
+
expect(subject.show(1, { foo: :bar })).to be_kind_of Contactually::Account
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#destroy' do
|
52
|
+
it 'calls the api with correct params' do
|
53
|
+
allow(@master).to receive(:call).with('accounts/1.json', :delete, {})
|
54
|
+
subject.destroy(1)
|
55
|
+
expect(@master).to have_received(:call)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|