pipedrive.rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +5 -0
  3. data/.gitignore +23 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +17 -0
  6. data/.travis.yml +10 -0
  7. data/Gemfile +20 -0
  8. data/Guardfile +24 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +100 -0
  11. data/Rakefile +27 -0
  12. data/defaults.reek +11 -0
  13. data/lib/pipedrive.rb +92 -0
  14. data/lib/pipedrive/activity.rb +8 -0
  15. data/lib/pipedrive/activity_type.rb +12 -0
  16. data/lib/pipedrive/base.rb +87 -0
  17. data/lib/pipedrive/deal.rb +8 -0
  18. data/lib/pipedrive/deal_field.rb +11 -0
  19. data/lib/pipedrive/file.rb +8 -0
  20. data/lib/pipedrive/filter.rb +6 -0
  21. data/lib/pipedrive/goal.rb +8 -0
  22. data/lib/pipedrive/note.rb +8 -0
  23. data/lib/pipedrive/operations/create.rb +11 -0
  24. data/lib/pipedrive/operations/delete.rb +15 -0
  25. data/lib/pipedrive/operations/read.rb +29 -0
  26. data/lib/pipedrive/operations/update.rb +15 -0
  27. data/lib/pipedrive/organization.rb +8 -0
  28. data/lib/pipedrive/organization_field.rb +11 -0
  29. data/lib/pipedrive/person.rb +18 -0
  30. data/lib/pipedrive/person_field.rb +11 -0
  31. data/lib/pipedrive/product.rb +8 -0
  32. data/lib/pipedrive/product_field.rb +11 -0
  33. data/lib/pipedrive/railties.rb +7 -0
  34. data/lib/pipedrive/role.rb +8 -0
  35. data/lib/pipedrive/stage.rb +8 -0
  36. data/lib/pipedrive/utils.rb +18 -0
  37. data/lib/pipedrive/version.rb +3 -0
  38. data/pipedrive.gemspec +29 -0
  39. data/spec/lib/pipedrive/activity_spec.rb +9 -0
  40. data/spec/lib/pipedrive/activity_type_spec.rb +9 -0
  41. data/spec/lib/pipedrive/base_spec.rb +122 -0
  42. data/spec/lib/pipedrive/deal_field_spec.rb +9 -0
  43. data/spec/lib/pipedrive/deal_spec.rb +9 -0
  44. data/spec/lib/pipedrive/file_spec.rb +9 -0
  45. data/spec/lib/pipedrive/filter_spec.rb +9 -0
  46. data/spec/lib/pipedrive/goal_spec.rb +9 -0
  47. data/spec/lib/pipedrive/note_spec.rb +9 -0
  48. data/spec/lib/pipedrive/ogranization_spec.rb +9 -0
  49. data/spec/lib/pipedrive/operations/create_spec.rb +16 -0
  50. data/spec/lib/pipedrive/operations/delete_spec.rb +22 -0
  51. data/spec/lib/pipedrive/operations/read_spec.rb +69 -0
  52. data/spec/lib/pipedrive/operations/update_spec.rb +20 -0
  53. data/spec/lib/pipedrive/organization_field_spec.rb +9 -0
  54. data/spec/lib/pipedrive/person_field_spec.rb +9 -0
  55. data/spec/lib/pipedrive/person_spec.rb +24 -0
  56. data/spec/lib/pipedrive/product_field_spec.rb +9 -0
  57. data/spec/lib/pipedrive/product_spec.rb +9 -0
  58. data/spec/lib/pipedrive_spec.rb +65 -0
  59. data/spec/spec_helper.rb +17 -0
  60. metadata +235 -0
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Deal < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Pipedrive
2
+ class DealField < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Delete
6
+
7
+ def entity_name
8
+ 'dealFields'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class File < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module Pipedrive
2
+ class Filter < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Delete
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Goal < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Note < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Pipedrive
2
+ module Operations
3
+ module Create
4
+ extend ActiveSupport::Concern
5
+
6
+ def create(params)
7
+ make_api_call(:post, params)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Pipedrive
2
+ module Operations
3
+ module Delete
4
+ extend ActiveSupport::Concern
5
+
6
+ def delete(id)
7
+ make_api_call(:delete, id)
8
+ end
9
+
10
+ def delete_all
11
+ make_api_call(:delete)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ module Pipedrive
2
+ module Operations
3
+ module Read
4
+ extend ActiveSupport::Concern
5
+ include ::Enumerable
6
+ include ::Pipedrive::Utils
7
+
8
+ # This method smells of :reek:TooManyStatements but ignores them
9
+ def each(params = {})
10
+ return to_enum(:each, params) unless block_given?
11
+ follow_pagination(:chunk, [], params) { |item| yield item }
12
+ end
13
+
14
+ def all(params = {})
15
+ each(params).to_a
16
+ end
17
+
18
+ def chunk(params = {})
19
+ res = make_api_call(:get, params)
20
+ return [] unless res.success?
21
+ res
22
+ end
23
+
24
+ def find_by_id(id)
25
+ make_api_call(:get, id)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ module Pipedrive
2
+ module Operations
3
+ module Update
4
+ extend ActiveSupport::Concern
5
+
6
+ def update(*args)
7
+ params = args.extract_options!
8
+ params.symbolize_keys!
9
+ id = params.delete(:id) || args[0]
10
+ fail 'id must be provided' unless id
11
+ make_api_call(:put, id, params)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Organization < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Pipedrive
2
+ class OrganizationField < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Delete
6
+
7
+ def entity_name
8
+ 'organizationFields'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module Pipedrive
2
+ class Person < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ include ::Pipedrive::Utils
8
+
9
+ def find_by_name(*args)
10
+ params = args.extract_options!
11
+ params[:term] ||= args[0]
12
+ fail 'term is missing' unless params[:term]
13
+ params[:search_by_email] ||= args[1] ? 1 : 0
14
+ return to_enum(:find_by_name, params) unless block_given?
15
+ follow_pagination(:make_api_call, [:get, 'find'], params) { |item| yield item }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Pipedrive
2
+ class PersonField < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Delete
6
+
7
+ def entity_name
8
+ 'personFields'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Product < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Pipedrive
2
+ class ProductField < Base
3
+ include ::Pipedrive::Operations::Read
4
+ include ::Pipedrive::Operations::Create
5
+ include ::Pipedrive::Operations::Delete
6
+
7
+ def entity_name
8
+ 'productFields'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Pipedrive
2
+ class Railties < ::Rails::Railtie
3
+ initializer 'Pipedrive logger' do
4
+ ::Pipedrive.logger = ::Rails.logger
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Role < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Pipedrive
2
+ class Stage < Base
3
+ include ::Pipedrive::Operations::Create
4
+ include ::Pipedrive::Operations::Read
5
+ include ::Pipedrive::Operations::Update
6
+ include ::Pipedrive::Operations::Delete
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module Pipedrive
2
+ module Utils
3
+ extend ActiveSupport::Concern
4
+
5
+ def follow_pagination(method, args, params)
6
+ start = params[:start] || 0
7
+ loop do
8
+ res = __send__(method, *args, params.merge(start: start))
9
+ break if !res.try(:data) || !res.success?
10
+ res.data.each do |item|
11
+ yield item
12
+ end
13
+ break unless res.try(:additional_data).try(:pagination).try(:more_items_in_collection?)
14
+ start = res.try(:additional_data).try(:pagination).try(:next_start)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Pipedrive
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pipedrive/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "pipedrive.rb"
8
+ gem.version = Pipedrive::VERSION
9
+ gem.authors = ["Alexander Simonov"]
10
+ gem.email = ["alex@simonov.me"]
11
+ gem.summary = %q{Pipedrive.com API Wrapper}
12
+ gem.description = %q{Pipedrive.com API Wrapper}
13
+ gem.homepage = 'https://github.com/dotpromo/pipedrive.rb'
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files -z`.split("\x0")
17
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency('faraday')
22
+ gem.add_dependency('faraday_middleware')
23
+ gem.add_dependency('activesupport', '>= 4.0.0')
24
+ gem.add_dependency('hashie', '>= 3.0')
25
+ gem.add_development_dependency('bundler', '~> 1.6')
26
+ gem.add_development_dependency('rake')
27
+ gem.add_development_dependency('rspec', '>= 3.0')
28
+ gem.add_development_dependency('webmock')
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ::Pipedrive::Activity do
4
+ subject { described_class.new('token') }
5
+ context '#entity_name' do
6
+ subject { super().entity_name }
7
+ it { is_expected.to eq('activities') }
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ::Pipedrive::ActivityType do
4
+ subject { described_class.new('token') }
5
+ context '#entity_name' do
6
+ subject { super().entity_name }
7
+ it { is_expected.to eq('activityTypes') }
8
+ end
9
+ end
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ::Pipedrive::Base do
4
+ subject { described_class.new('token') }
5
+ context '#entity_name' do
6
+ subject { super().entity_name }
7
+ it { is_expected.to eq described_class.name.split('::')[-1].downcase.pluralize }
8
+ end
9
+
10
+ context '::faraday_options' do
11
+ subject { described_class.faraday_options }
12
+ it { is_expected.to eq({
13
+ url: 'https://api.pipedrive.com',
14
+ headers: { accept: 'application/json', user_agent: 'Pipedrive Ruby Client v0.0.1' }
15
+ }) }
16
+ end
17
+
18
+ context '::connection' do
19
+ subject { super().connection }
20
+ it { is_expected.to be_kind_of(::Faraday::Connection) }
21
+ end
22
+
23
+ context '#failed_response' do
24
+ let(:res) { double('res', body: ::Hashie::Mash.new({}), status: status) }
25
+ subject { super().failed_response(res) }
26
+ context 'status is 401' do
27
+ let(:status) { 401 }
28
+ it { is_expected.to eq(::Hashie::Mash.new({
29
+ failed: false,
30
+ not_authorized: true,
31
+ success: false
32
+ })) }
33
+ end
34
+ context 'status is 420' do
35
+ let(:status) { 420 }
36
+ it { is_expected.to eq(::Hashie::Mash.new({
37
+ failed: true,
38
+ not_authorized: false,
39
+ success: false
40
+ })) }
41
+ end
42
+ context 'status is 400' do
43
+ let(:status) { 400 }
44
+ it { is_expected.to eq(::Hashie::Mash.new({
45
+ failed: false,
46
+ not_authorized: false,
47
+ success: false
48
+ })) }
49
+ end
50
+ end
51
+ context '#make_api_call' do
52
+ it 'should failed no method' do
53
+ expect { subject.make_api_call(test: 'foo') }.to raise_error('method param missing')
54
+ end
55
+ context 'without id' do
56
+ it 'should call :get' do
57
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
58
+ expect_any_instance_of(::Faraday::Connection).to receive(:get).with('/v1/bases?api_token=token', {}).and_call_original
59
+ expect(subject.make_api_call(:get))
60
+ end
61
+ it 'should call :post' do
62
+ stub_request(:post, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
63
+ expect_any_instance_of(::Faraday::Connection).to receive(:post).with('/v1/bases?api_token=token', { test: 'bar' }).and_call_original
64
+ expect(subject.make_api_call(:post, test: 'bar'))
65
+ end
66
+ it 'should call :put' do
67
+ stub_request(:put, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
68
+ expect_any_instance_of(::Faraday::Connection).to receive(:put).with('/v1/bases?api_token=token', { test: 'bar' }).and_call_original
69
+ expect(subject.make_api_call(:put, test: 'bar'))
70
+ end
71
+ it 'should use field_selector properly' do
72
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases:(a,b,c)?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
73
+ expect_any_instance_of(::Faraday::Connection).to receive(:get).
74
+ with('/v1/bases:(a,b,c)?api_token=token', {}).and_call_original
75
+ expect(subject.make_api_call(:get, fields_to_select: %w(a b c)))
76
+ end
77
+ it 'should not use field_selector if it empty' do
78
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
79
+ expect_any_instance_of(::Faraday::Connection).to receive(:get).
80
+ with('/v1/bases?api_token=token', {}).and_call_original
81
+ expect(subject.make_api_call(:get, fields_to_select: []))
82
+ end
83
+ it 'should retry if Errno::ETIMEDOUT' do
84
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
85
+ connection = subject.connection
86
+ allow(subject).to receive(:connection).and_return(connection)
87
+ allow(connection).to receive(:get).
88
+ with('/v1/bases?api_token=token', {}).and_raise(Errno::ETIMEDOUT)
89
+ expect(connection).to receive(:get).
90
+ with('/v1/bases?api_token=token', {}).and_call_original
91
+ expect(subject.make_api_call(:get, fields_to_select: []))
92
+ end
93
+ end
94
+ context 'with id' do
95
+ it 'should call :get' do
96
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases/12?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
97
+ expect_any_instance_of(::Faraday::Connection).to receive(:get).with('/v1/bases/12?api_token=token', {}).and_call_original
98
+ expect(subject.make_api_call(:get, 12))
99
+ end
100
+ it 'should call :post' do
101
+ stub_request(:post, 'https://api.pipedrive.com/v1/bases/13?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
102
+ expect_any_instance_of(::Faraday::Connection).to receive(:post).with('/v1/bases/13?api_token=token', { test: 'bar' }).and_call_original
103
+ expect(subject.make_api_call(:post, 13, test: 'bar'))
104
+ end
105
+ it 'should call :put' do
106
+ stub_request(:put, 'https://api.pipedrive.com/v1/bases/14?api_token=token').to_return(:status => 200, :body => {}, :headers => {})
107
+ expect_any_instance_of(::Faraday::Connection).to receive(:put).with('/v1/bases/14?api_token=token', { test: 'bar' }).and_call_original
108
+ expect(subject.make_api_call(:put, 14, test: 'bar'))
109
+ end
110
+ end
111
+ it 'should call Hashie::Mash if return empty string' do
112
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 200, :body => '', :headers => {})
113
+ expect(::Hashie::Mash).to receive(:new).with(success: true).and_call_original
114
+ expect(subject.make_api_call(:get))
115
+ end
116
+ it 'should call #failed_response if failed status' do
117
+ stub_request(:get, 'https://api.pipedrive.com/v1/bases?api_token=token').to_return(:status => 400, :body => '', :headers => {})
118
+ expect(subject).to receive(:failed_response)
119
+ expect(subject.make_api_call(:get))
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ::Pipedrive::DealField do
4
+ subject { described_class.new('token') }
5
+ context '#entity_name' do
6
+ subject { super().entity_name }
7
+ it { is_expected.to eq('dealFields') }
8
+ end
9
+ end