pipe_drive_ruby_wrapper 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.
- checksums.yaml +7 -0
- data/README.md +76 -0
- data/lib/pipe_drive/base.rb +101 -0
- data/lib/pipe_drive/deal.rb +6 -0
- data/lib/pipe_drive/deal_field.rb +11 -0
- data/lib/pipe_drive/exception.rb +36 -0
- data/lib/pipe_drive/field_base.rb +58 -0
- data/lib/pipe_drive/organization.rb +6 -0
- data/lib/pipe_drive/organization_field.rb +11 -0
- data/lib/pipe_drive/overall_source_base.rb +46 -0
- data/lib/pipe_drive/person.rb +20 -0
- data/lib/pipe_drive/person_field.rb +11 -0
- data/lib/pipe_drive/pipeline.rb +7 -0
- data/lib/pipe_drive/resource_base.rb +86 -0
- data/lib/pipe_drive/send_request.rb +103 -0
- data/lib/pipe_drive/stage.rb +19 -0
- data/lib/pipe_drive_ruby_wrapper.rb +68 -0
- data/spec/lib/deal_spec.rb +15 -0
- data/spec/lib/organization_spec.rb +15 -0
- data/spec/lib/person_spec.rb +15 -0
- data/spec/lib/send_request_spec.rb +10 -0
- data/spec/pipe_drive_ruby_wrapper_spec.rb +34 -0
- data/spec/spec_helper.rb +28 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2f24bb5abbf918344616ceabd2c5934d827b679dc3926e0a76b060556f8b0ae1
|
4
|
+
data.tar.gz: 187ecc5a550e53683944140ddd6d5581e8c75220986395ede513143552983d5c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 144a7b8c10025bf67798ccfd139df42fd68a294d5ab34cbfc29d4ec2b78b23967db94676e3c65a4fb9b865e019257377889def5d2b7b357a03ff95357b968c9e
|
7
|
+
data.tar.gz: 26487cc9cc903902a46b8dcf68cc10d59963350d917f728ebbfa4995761634bce3590f1841042965c38e06b86176f7d38a5371437f0cc6592e4ee6530c89882f
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# PipeDrive Ruby Wrapper
|
2
|
+
ruby wrapper of pipe drive api
|
3
|
+
|
4
|
+
### Install
|
5
|
+
##### Gem
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem install pipe_drive_ruby_wrapper
|
9
|
+
```
|
10
|
+
##### Gemfile
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'pipe_drive_ruby_wrapper'
|
14
|
+
```
|
15
|
+
|
16
|
+
### Configure
|
17
|
+
|
18
|
+
*You must call below instruction before you start to use this gem*
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
PipeDrive.setup do |config|
|
22
|
+
config.api_token = [Your API Token obtain from pipedrive website]
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
### Usage
|
27
|
+
*You should require first*
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'pipe_drive_ruby_wrapper'
|
31
|
+
```
|
32
|
+
|
33
|
+
use person resource as example
|
34
|
+
|
35
|
+
* list all resource
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
PipeDrive::Person.list
|
39
|
+
```
|
40
|
+
|
41
|
+
* find by id
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
PipeDrive::Person.find_by_id(1)
|
45
|
+
```
|
46
|
+
|
47
|
+
* find by other field (only return one resource)
|
48
|
+
* strict (only the same can be found)
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
PipeDrive::Person.find_by(:name, {name: 'Test'}, PipeDrive::STRICT)
|
52
|
+
```
|
53
|
+
|
54
|
+
* not strict (can be found if similar)
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
PipeDrive::Person.find_by(:name, {name: 'Test'})
|
58
|
+
```
|
59
|
+
|
60
|
+
* search for specific field (return array of resources, can be found if similar)
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
PipeDrive::Person.search(:name, {name: 'Test'})
|
64
|
+
```
|
65
|
+
|
66
|
+
* update resource
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
PipeDrive::Person.update(1, {name: 'new name'})
|
70
|
+
```
|
71
|
+
|
72
|
+
* delete resource
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
PipeDrive::Person.delete(1)
|
76
|
+
```
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class Base < OpenStruct
|
3
|
+
|
4
|
+
def initialize(attrs)
|
5
|
+
struct_attrs = attrs[:data] || PipeDrive.hash_except(attrs, [:additional_data])
|
6
|
+
struct_attrs.merge!(attrs[:additional_data]) unless attrs[:additional_data].nil?
|
7
|
+
|
8
|
+
super(struct_attrs)
|
9
|
+
end
|
10
|
+
|
11
|
+
def requester
|
12
|
+
PipeDrive.requester
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(opts)
|
16
|
+
path = "/#{self.class.resource_name}s/#{id}"
|
17
|
+
opts.transform_keys!{|key| field_keys[key] || key}
|
18
|
+
requester.http_put(path, opts) do |result|
|
19
|
+
new(result)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete
|
24
|
+
path = "/#{self.class.resource_name}s/#{id}"
|
25
|
+
requester.http_del(path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def parameterize(target_string, separator)
|
29
|
+
self.class.parameterize(target_string, separator)
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def requester
|
34
|
+
PipeDrive.requester
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_by_id(id)
|
38
|
+
path = "/#{resource_name}s/#{id}"
|
39
|
+
requester.http_get(path) do |result|
|
40
|
+
result[:data].nil? ? nil : new(result)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def create(opts)
|
45
|
+
opts.transform_keys!{|key| field_keys[key] || key}
|
46
|
+
requester.http_post("/#{resource_name}s", opts) do |result|
|
47
|
+
new(result)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def update(id, opts)
|
52
|
+
path = "/#{resource_name}s/#{id}"
|
53
|
+
opts.transform_keys!{|key| field_keys[key] || key}
|
54
|
+
requester.http_put(path, opts) do |result|
|
55
|
+
new(result)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(id)
|
60
|
+
path = "/#{resource_name}s/#{id}"
|
61
|
+
requester.http_del(path){|result| puts result}
|
62
|
+
end
|
63
|
+
|
64
|
+
def search_and_setup_by(type, opts, strict=false)
|
65
|
+
target = find_by(type, opts, strict)
|
66
|
+
if target.nil?
|
67
|
+
create(opts)
|
68
|
+
else
|
69
|
+
target.update(opts)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def parameterize(target_string, separator)
|
74
|
+
target_string.gsub!(/[\-_\ ]+/, separator)
|
75
|
+
target_string.downcase
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def list_objects(attrs)
|
81
|
+
return [] if attrs.nil? || attrs.empty?
|
82
|
+
if attrs[:data].nil?
|
83
|
+
struct_attrs = attrs
|
84
|
+
elsif attrs[:additional_data].nil?
|
85
|
+
struct_attrs = attrs[:data].map do |data|
|
86
|
+
data
|
87
|
+
end
|
88
|
+
else
|
89
|
+
struct_attrs = attrs[:data].map do |data|
|
90
|
+
data.merge(attrs[:additional_data])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
struct_attrs.map do |struct_attr|
|
95
|
+
new(struct_attr)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class MissingApiToken < StandardError
|
3
|
+
def initialize
|
4
|
+
err_msg = "api token not found, please setup with
|
5
|
+
PipeDrive.setup do |config|
|
6
|
+
config.api_token = [Your API Token]
|
7
|
+
end
|
8
|
+
"
|
9
|
+
super(err_msg)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class NotAllowSearchType < StandardError
|
14
|
+
def initialize(type=nil)
|
15
|
+
super("#{type} not allow search type")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class NotProvideAssignType < StandardError
|
20
|
+
def initialize(type=nil)
|
21
|
+
super("not provide #{type}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class TargetNotFound < StandardError
|
26
|
+
def initialize(class_name, search_type, search_value)
|
27
|
+
super("#{class_name}: search #{search_type} for #{search_value} not found")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class RequestError < StandardError
|
32
|
+
def initialize(response)
|
33
|
+
super(response.to_json)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class FieldBase < Base
|
3
|
+
def add_to_field_keys
|
4
|
+
resource = self.class.correspond_resource.to_sym
|
5
|
+
field_name = parameterize(name, '_').to_sym
|
6
|
+
PipeDrive.field_keys[resource][field_name] = key
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def correspond_resource
|
12
|
+
resource_name.sub('Field', '')
|
13
|
+
end
|
14
|
+
|
15
|
+
def list(&block)
|
16
|
+
path = "/#{resource_name}s"
|
17
|
+
resources = requester.http_get(path) do |result|
|
18
|
+
result[:data].nil? ? [] : list_objects(result)
|
19
|
+
end
|
20
|
+
resources.each do |resource|
|
21
|
+
yield resource
|
22
|
+
end if block_given?
|
23
|
+
resources
|
24
|
+
end
|
25
|
+
|
26
|
+
def create(opts)
|
27
|
+
new_field = super(opts)
|
28
|
+
new_field.add_to_field_keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def custom_field_setup
|
32
|
+
resource = correspond_resource.to_sym
|
33
|
+
list.each do |field|
|
34
|
+
field_name = parameterize(field.name, '_').to_sym
|
35
|
+
PipeDrive.field_keys[resource][field_name] = field.key
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def cache_keys
|
40
|
+
PipeDrive.field_keys[correspond_resource.to_sym]
|
41
|
+
end
|
42
|
+
|
43
|
+
def pipedrive_key_of(field_name)
|
44
|
+
cache_field_name = parameterize(field_name, '_').to_sym
|
45
|
+
pipedrive_key = cache_keys[cache_field_name]
|
46
|
+
return pipedrive_key unless pipedrive_key.nil?
|
47
|
+
custom_field_setup
|
48
|
+
pipedrive_key = cache_keys[cache_field_name]
|
49
|
+
if pipedrive_key.nil?
|
50
|
+
raise TargetNotFound.new(self.name, :name, field_name)
|
51
|
+
else
|
52
|
+
pipedrive_key
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class OverallSourceBase < ResourceBase
|
3
|
+
|
4
|
+
def deals(start_from=0, per_page=DEFAULT_PER_PAGE, options={}, &block)
|
5
|
+
path = "/#{resource_name}s/#{id}/deals"
|
6
|
+
params = {start: start_from, limit: per_page}
|
7
|
+
params.merge!(options)
|
8
|
+
pagination(path, params, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
|
14
|
+
def list(options={}, &block)
|
15
|
+
path = "/#{resource_name}s"
|
16
|
+
resources = requester.http_get(path, options) do |result|
|
17
|
+
result[:data].nil? ? [] : list_objects(result)
|
18
|
+
end
|
19
|
+
resources.each do |resource|
|
20
|
+
yield resource
|
21
|
+
end if block_given?
|
22
|
+
resources
|
23
|
+
end
|
24
|
+
|
25
|
+
def search(type, opts)
|
26
|
+
raise NotAllowSearchType.new(type) unless const_get('ALLOW_FOR_SEARCH_TERMS').include?(type)
|
27
|
+
raise NotProvideAssignType.new(type) if opts[type].nil?
|
28
|
+
allow_search_opts = const_get('ALLOW_FOR_ADDITION_SEARCH_OPTS') + [type]
|
29
|
+
opts = opts.slice(*allow_search_opts)
|
30
|
+
list.select do |resource|
|
31
|
+
is_match = true
|
32
|
+
opts.each_pair do |key, value|
|
33
|
+
resource_value = resource.send(key)
|
34
|
+
if resource_value.is_a?(String)
|
35
|
+
(is_match = false) && break unless resource_value.include?(value)
|
36
|
+
else
|
37
|
+
(is_match = false) && break unless resource_value == value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
is_match
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class Person < ResourceBase
|
3
|
+
ALLOW_FOR_SEARCH_TERMS = %i[name email]
|
4
|
+
ALLOW_FOR_ADDITION_SEARCH_OPTS = %i[org_id start limit]
|
5
|
+
|
6
|
+
def activities(start_from=0, per_page=DEFAULT_PER_PAGE, options={}, &block)
|
7
|
+
path = "/persons/#{id}/activities"
|
8
|
+
params = {start: start_from, limit: per_page}
|
9
|
+
params.merge!(options)
|
10
|
+
pagination(path, params, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def deals(start_from=0, per_page=DEFAULT_PER_PAGE, options={}, &block)
|
14
|
+
path = "/persons/#{id}/deals"
|
15
|
+
params = {start: start_from, limit: per_page}
|
16
|
+
params.merge!(options)
|
17
|
+
pagination(path, params, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class ResourceBase < Base
|
3
|
+
|
4
|
+
protected
|
5
|
+
|
6
|
+
def pagination(path, params, &block)
|
7
|
+
self.class.send(:pagination, path, params, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def resource_name
|
13
|
+
name.split('::').last.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def field_keys
|
17
|
+
PipeDrive.field_keys[resource_name.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def list(options={}, &block)
|
21
|
+
path = "/#{resource_name}s"
|
22
|
+
params = {start_from: 0, limit: DEFAULT_PER_PAGE}
|
23
|
+
params.merge!(options)
|
24
|
+
pagination(path, params, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def pagination_list(start_from=0, per_page=DEFAULT_PER_PAGE, options={}, &block)
|
28
|
+
path = "/#{resource_name}s"
|
29
|
+
params = {start: start_from, limit: per_page}
|
30
|
+
params.merge!(options)
|
31
|
+
resources = requester.http_get(path, params) do |result|
|
32
|
+
result[:data].nil? ? nil : list_objects(result)
|
33
|
+
end
|
34
|
+
resources.each do |resource|
|
35
|
+
yield resource
|
36
|
+
end if block_given?
|
37
|
+
resources
|
38
|
+
end
|
39
|
+
|
40
|
+
def search(type, opts)
|
41
|
+
raise NotAllowSearchType.new(type) unless const_get('ALLOW_FOR_SEARCH_TERMS').include?(type)
|
42
|
+
raise NotProvideAssignType.new(type) if opts[type].nil?
|
43
|
+
params = {term: opts[type]}
|
44
|
+
allow_search_opts = const_get('ALLOW_FOR_ADDITION_SEARCH_OPTS')
|
45
|
+
params.merge!(opts.slice(*allow_search_opts))
|
46
|
+
requester.http_get("/#{resource_name}s/find", params) do |result|
|
47
|
+
result[:data].nil? ? nil : list_objects(result)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_by(type, opts, strict=false)
|
52
|
+
targets = search(type, opts)
|
53
|
+
return if targets.nil? || targets.empty?
|
54
|
+
if strict
|
55
|
+
targets.find do |target|
|
56
|
+
target.send(type) == opts[type]
|
57
|
+
end
|
58
|
+
else
|
59
|
+
targets.first
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
def pagination(path, params, &block)
|
66
|
+
resources = []
|
67
|
+
loop do
|
68
|
+
next_start_from = requester.http_get(path, params) do |result|
|
69
|
+
return resources if result[:data].nil?
|
70
|
+
items = list_objects(result)
|
71
|
+
resources += items
|
72
|
+
items.each do |item|
|
73
|
+
yield item
|
74
|
+
end if block_given?
|
75
|
+
result.dig(:additional_data, :pagination, :next_start)
|
76
|
+
end
|
77
|
+
break if next_start_from.nil?
|
78
|
+
params[:start] = next_start_from
|
79
|
+
end
|
80
|
+
resources
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class SendRequest
|
3
|
+
attr_reader :host
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
raise MissingApiToken.new if PipeDrive.api_token.nil?
|
7
|
+
@host = PipeDrive.host
|
8
|
+
@api_token = PipeDrive.api_token
|
9
|
+
end
|
10
|
+
|
11
|
+
def http_get(path, params={}, header={}, &block)
|
12
|
+
begin
|
13
|
+
full_url = "#{host}/#{API_VERSION}#{path}"
|
14
|
+
uri = URI(full_url)
|
15
|
+
params.merge!(api_token: @api_token)
|
16
|
+
uri.query = URI.encode_www_form(params)
|
17
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
18
|
+
http.use_ssl = uri.scheme == 'https'
|
19
|
+
|
20
|
+
request = Net::HTTP::Get.new(uri.request_uri, header)
|
21
|
+
response = http.request(request)
|
22
|
+
result = handle_response(response)
|
23
|
+
rescue Exception => e
|
24
|
+
result = server_error_response(e.message)
|
25
|
+
end
|
26
|
+
return result unless block_given?
|
27
|
+
raise RequestError.new(result) unless success_result?(result)
|
28
|
+
yield PipeDrive.hash_except(result, [:status])
|
29
|
+
end
|
30
|
+
|
31
|
+
def http_post(path, params={}, header={}, &block)
|
32
|
+
body_request(:post, path, params, header, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def http_put(path, params={}, header={}, &block)
|
36
|
+
body_request(:put, path, params, header, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def http_del(path, params={}, header={}, &block)
|
40
|
+
body_request(:delete, path, params, header, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def body_request(method, path, params={}, header={}, &block)
|
46
|
+
begin
|
47
|
+
full_url = "#{host}/#{API_VERSION}#{path}?api_token=#{@api_token}"
|
48
|
+
uri = URI(full_url)
|
49
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
50
|
+
http.use_ssl = uri.scheme == 'https'
|
51
|
+
header['Content-Type'] = 'application/json'
|
52
|
+
|
53
|
+
request = Net::HTTP.const_get(method.to_s.capitalize).new(uri.request_uri, header)
|
54
|
+
request.body = params.to_json
|
55
|
+
response = http.request(request)
|
56
|
+
result = handle_response(response)
|
57
|
+
rescue Exception => e
|
58
|
+
result = server_error_response(e.message)
|
59
|
+
end
|
60
|
+
return result unless block_given?
|
61
|
+
raise RequestError.new(result) unless success_result?(result)
|
62
|
+
yield PipeDrive.hash_except(result, [:status])
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def handle_response(response)
|
68
|
+
result = {status: response.code.to_i}
|
69
|
+
|
70
|
+
begin
|
71
|
+
body = Oj.load(response.body)
|
72
|
+
rescue
|
73
|
+
body = {body: response.body}
|
74
|
+
end
|
75
|
+
body = deep_symbolize_keys(body)
|
76
|
+
result.merge body
|
77
|
+
end
|
78
|
+
|
79
|
+
def server_error_response(err_msg)
|
80
|
+
{status: 500, message: err_msg}
|
81
|
+
end
|
82
|
+
|
83
|
+
def success_result?(result)
|
84
|
+
result[:status].is_a?(Integer) && (result[:status] / 100 == 2)
|
85
|
+
end
|
86
|
+
|
87
|
+
def deep_symbolize_keys(data)
|
88
|
+
new_data = {}
|
89
|
+
data.each_pair do |key, value|
|
90
|
+
if value.is_a?(Hash)
|
91
|
+
new_data[key.to_sym] = deep_symbolize_keys(value)
|
92
|
+
elsif value.is_a?(Array)
|
93
|
+
new_data[key.to_sym] = value.map do |v|
|
94
|
+
deep_symbolize_keys(v)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
new_data[key.to_sym] = value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
new_data
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PipeDrive
|
2
|
+
class Stage < OverallSourceBase
|
3
|
+
ALLOW_FOR_SEARCH_TERMS = %i[name]
|
4
|
+
ALLOW_FOR_ADDITION_SEARCH_OPTS = %i[pipeline_name pipeline_id]
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def setup_stage_ids
|
9
|
+
list.each do |stage|
|
10
|
+
pipeline_name = parameterize(stage.pipeline_name, '_').to_sym
|
11
|
+
stage_name = parameterize(stage.name, '_').to_sym
|
12
|
+
PipeDrive.stage_ids[pipeline_name][stage_name] = stage.id
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'oj'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module PipeDrive
|
7
|
+
API_VERSION = 'v1'
|
8
|
+
DEFAULT_PER_PAGE = 10
|
9
|
+
STRICT = true
|
10
|
+
|
11
|
+
RESOURCE_CLASSES = %w[Organization Person Deal]
|
12
|
+
FIELD_CLASSES = %w[OrganizationField PersonField DealField]
|
13
|
+
|
14
|
+
class << self; attr_accessor :api_token, :field_keys, :stage_ids; end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def setup
|
18
|
+
yield self
|
19
|
+
|
20
|
+
if field_keys.nil?
|
21
|
+
self.field_keys = Hash.new{|hash, key| hash[key] = {}}
|
22
|
+
FIELD_CLASSES.each do |class_name|
|
23
|
+
const_get(class_name).custom_field_setup
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if stage_ids.nil?
|
28
|
+
self.stage_ids = Hash.new{|hash, key| hash[key] = {}}
|
29
|
+
Stage.setup_stage_ids
|
30
|
+
end
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def host
|
36
|
+
"https://api.pipedrive.com"
|
37
|
+
end
|
38
|
+
|
39
|
+
def requester
|
40
|
+
SendRequest.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def hash_except(hash, except_keys)
|
44
|
+
all_keys = hash.keys
|
45
|
+
remain_keys = all_keys - except_keys
|
46
|
+
hash.slice(*remain_keys)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
require 'pipe_drive/base'
|
53
|
+
require 'pipe_drive/exception'
|
54
|
+
require 'pipe_drive/send_request'
|
55
|
+
|
56
|
+
require 'pipe_drive/resource_base'
|
57
|
+
require 'pipe_drive/organization'
|
58
|
+
require 'pipe_drive/person'
|
59
|
+
require 'pipe_drive/deal'
|
60
|
+
|
61
|
+
require 'pipe_drive/overall_source_base'
|
62
|
+
require 'pipe_drive/pipeline'
|
63
|
+
require 'pipe_drive/stage'
|
64
|
+
|
65
|
+
require 'pipe_drive/field_base'
|
66
|
+
require 'pipe_drive/organization_field'
|
67
|
+
require 'pipe_drive/person_field'
|
68
|
+
require 'pipe_drive/deal_field'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
RSpec.describe PipeDrive::Deal do
|
2
|
+
|
3
|
+
context '.resource_name' do
|
4
|
+
it 'should return resource name' do
|
5
|
+
expect(PipeDrive::Deal.resource_name).to eq('deal')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
context '.field_keys' do
|
10
|
+
it 'should obtain person custom field' do
|
11
|
+
deal_custom_fields = {product: 'product key'}
|
12
|
+
expect(PipeDrive::Deal.field_keys).to eq(deal_custom_fields)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
RSpec.describe PipeDrive::Organization do
|
2
|
+
|
3
|
+
context '.resource_name' do
|
4
|
+
it 'should return resource name' do
|
5
|
+
expect(PipeDrive::Organization.resource_name).to eq('organization')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
context '.field_keys' do
|
10
|
+
it 'should obtain person custom field' do
|
11
|
+
org_custom_fields = {region: 'region key'}
|
12
|
+
expect(PipeDrive::Organization.field_keys).to eq(org_custom_fields)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
RSpec.describe PipeDrive::Person do
|
2
|
+
|
3
|
+
context '.resource_name' do
|
4
|
+
it 'should return resource name' do
|
5
|
+
expect(PipeDrive::Person.resource_name).to eq('person')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
context '.field_keys' do
|
10
|
+
it 'should obtain person custom field' do
|
11
|
+
person_custom_fields = {role: 'role key'}
|
12
|
+
expect(PipeDrive::Person.field_keys).to eq(person_custom_fields)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
RSpec.describe PipeDrive::SendRequest do
|
2
|
+
|
3
|
+
context '.initialize' do
|
4
|
+
it 'should raise missing api token error if not set api token' do
|
5
|
+
PipeDrive.api_token = nil
|
6
|
+
expect{PipeDrive::SendRequest.new}.to raise_error(PipeDrive::MissingApiToken)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
RSpec.describe PipeDrive do
|
2
|
+
context '.setup' do
|
3
|
+
it 'should setup basic info for pipedrive' do
|
4
|
+
PipeDrive.setup do |config|
|
5
|
+
config.api_token = 'api token'
|
6
|
+
config.field_keys = {
|
7
|
+
person: {test: 'test_key'}
|
8
|
+
}
|
9
|
+
config.stage_ids = {
|
10
|
+
1 => {
|
11
|
+
test: 1
|
12
|
+
}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
expect(PipeDrive.api_token).to eq('api token')
|
16
|
+
expect(PipeDrive.field_keys).to eq({person: {test: 'test_key'}})
|
17
|
+
expect(PipeDrive.stage_ids).to eq({1 => {test: 1}})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context '.host' do
|
22
|
+
it 'should return host with setup organization name' do
|
23
|
+
pipe_drive_host = "https://api.pipedrive.com"
|
24
|
+
expect(PipeDrive.host).to eq(pipe_drive_host)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '.requester' do
|
29
|
+
it 'should setup requester with pipe drive host' do
|
30
|
+
pipe_drive_host = "https://api.pipedrive.com"
|
31
|
+
expect(PipeDrive.requester.host).to eq(pipe_drive_host)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'pipe_drive_ruby_wrapper'
|
3
|
+
|
4
|
+
Bundler.setup
|
5
|
+
|
6
|
+
ENV['RAILS_ENV'] ||= 'test'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
# some (optional) config here
|
10
|
+
end
|
11
|
+
|
12
|
+
PipeDrive.setup do |config|
|
13
|
+
config.api_token = 'api_token'
|
14
|
+
config.field_keys = {
|
15
|
+
organization: {
|
16
|
+
region: 'region key'
|
17
|
+
},
|
18
|
+
person: {
|
19
|
+
role: 'role key'
|
20
|
+
},
|
21
|
+
deal: {
|
22
|
+
product: 'product key'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
config.stage_ids = {
|
26
|
+
1 => {test: 1}
|
27
|
+
}
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pipe_drive_ruby_wrapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- JiaRou Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oj
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.3'
|
41
|
+
description: ruby wrapper of some pipe drive api
|
42
|
+
email: laura34963@kdanmobile.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files:
|
46
|
+
- README.md
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- lib/pipe_drive/base.rb
|
50
|
+
- lib/pipe_drive/deal.rb
|
51
|
+
- lib/pipe_drive/deal_field.rb
|
52
|
+
- lib/pipe_drive/exception.rb
|
53
|
+
- lib/pipe_drive/field_base.rb
|
54
|
+
- lib/pipe_drive/organization.rb
|
55
|
+
- lib/pipe_drive/organization_field.rb
|
56
|
+
- lib/pipe_drive/overall_source_base.rb
|
57
|
+
- lib/pipe_drive/person.rb
|
58
|
+
- lib/pipe_drive/person_field.rb
|
59
|
+
- lib/pipe_drive/pipeline.rb
|
60
|
+
- lib/pipe_drive/resource_base.rb
|
61
|
+
- lib/pipe_drive/send_request.rb
|
62
|
+
- lib/pipe_drive/stage.rb
|
63
|
+
- lib/pipe_drive_ruby_wrapper.rb
|
64
|
+
- spec/lib/deal_spec.rb
|
65
|
+
- spec/lib/organization_spec.rb
|
66
|
+
- spec/lib/person_spec.rb
|
67
|
+
- spec/lib/send_request_spec.rb
|
68
|
+
- spec/pipe_drive_ruby_wrapper_spec.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
homepage: https://github.com/laura34963/pipe_drive_ruby_wrapper
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options:
|
76
|
+
- "--charset=UTF-8"
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.3.1
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.7.7
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Some PipeDrive API Ruby Wrapper
|
95
|
+
test_files:
|
96
|
+
- spec/lib/deal_spec.rb
|
97
|
+
- spec/lib/organization_spec.rb
|
98
|
+
- spec/lib/person_spec.rb
|
99
|
+
- spec/lib/send_request_spec.rb
|
100
|
+
- spec/pipe_drive_ruby_wrapper_spec.rb
|
101
|
+
- spec/spec_helper.rb
|