contactually-ruby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +80 -0
  4. data/Rakefile +7 -0
  5. data/lib/contactually-ruby.rb +38 -0
  6. data/lib/contactually/accounts.rb +22 -0
  7. data/lib/contactually/api.rb +87 -0
  8. data/lib/contactually/buckets.rb +49 -0
  9. data/lib/contactually/contact_groupings.rb +16 -0
  10. data/lib/contactually/contacts.rb +54 -0
  11. data/lib/contactually/contents.rb +30 -0
  12. data/lib/contactually/errors.rb +21 -0
  13. data/lib/contactually/groupings.rb +36 -0
  14. data/lib/contactually/middleware/error_detector.rb +31 -0
  15. data/lib/contactually/notes.rb +31 -0
  16. data/lib/contactually/representer/account_representer.rb +15 -0
  17. data/lib/contactually/representer/bucket_representer.rb +16 -0
  18. data/lib/contactually/representer/contact_representer.rb +48 -0
  19. data/lib/contactually/representer/content_representer.rb +18 -0
  20. data/lib/contactually/representer/grouping_representer.rb +30 -0
  21. data/lib/contactually/representer/grouping_statistic_representer.rb +14 -0
  22. data/lib/contactually/representer/note_representer.rb +15 -0
  23. data/lib/contactually/representer/task_representer.rb +21 -0
  24. data/lib/contactually/tasks.rb +49 -0
  25. data/lib/contactually/utils.rb +44 -0
  26. data/lib/contactually/version.rb +3 -0
  27. data/spec/accounts_spec.rb +58 -0
  28. data/spec/api_spec.rb +125 -0
  29. data/spec/buckets_spec.rb +97 -0
  30. data/spec/contact_groupings_spec.rb +44 -0
  31. data/spec/contacts_spec.rb +133 -0
  32. data/spec/contents_spec.rb +80 -0
  33. data/spec/error_detector_spec.rb +24 -0
  34. data/spec/fixtures/account.json +10 -0
  35. data/spec/fixtures/accounts_index.json +19 -0
  36. data/spec/fixtures/bucket.json +8 -0
  37. data/spec/fixtures/buckets_index.json +41 -0
  38. data/spec/fixtures/contact.json +38 -0
  39. data/spec/fixtures/contacts_index.json +172 -0
  40. data/spec/fixtures/content.json +10 -0
  41. data/spec/fixtures/contents_index.json +29 -0
  42. data/spec/fixtures/grouping.json +19 -0
  43. data/spec/fixtures/groupings_index.json +28 -0
  44. data/spec/fixtures/note.json +7 -0
  45. data/spec/fixtures/note_destroy.json +4 -0
  46. data/spec/fixtures/notes_index.json +30 -0
  47. data/spec/fixtures/task.json +27 -0
  48. data/spec/fixtures/tasks_index.json +41 -0
  49. data/spec/groupings_spec.rb +85 -0
  50. data/spec/notes_spec.rb +85 -0
  51. data/spec/spec_helper.rb +14 -0
  52. data/spec/tasks_spec.rb +127 -0
  53. 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,3 @@
1
+ module Contactually
2
+ VERSION = "0.0.2"
3
+ 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