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