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