hubspot-api-ruby 0.8.1 → 0.9.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 +4 -4
- data/README.md +17 -9
- data/hubspot-api-ruby.gemspec +3 -4
- data/lib/hubspot/association.rb +79 -53
- data/lib/hubspot/company.rb +2 -2
- data/lib/hubspot/config.rb +10 -9
- data/lib/hubspot/connection.rb +20 -14
- data/lib/hubspot/contact.rb +5 -1
- data/lib/hubspot/contact_list.rb +0 -7
- data/lib/hubspot/custom_event.rb +25 -0
- data/lib/hubspot/deal.rb +34 -14
- data/lib/hubspot/exceptions.rb +2 -0
- data/lib/hubspot/meeting.rb +44 -0
- data/lib/hubspot/properties.rb +1 -1
- data/lib/hubspot-api-ruby.rb +2 -0
- data/spec/lib/hubspot/association_spec.rb +37 -32
- data/spec/lib/hubspot/blog_spec.rb +8 -14
- data/spec/lib/hubspot/company_properties_spec.rb +8 -11
- data/spec/lib/hubspot/company_spec.rb +5 -6
- data/spec/lib/hubspot/contact_list_spec.rb +76 -53
- data/spec/lib/hubspot/contact_properties_spec.rb +5 -34
- data/spec/lib/hubspot/contact_spec.rb +1 -3
- data/spec/lib/hubspot/custom_event_spec.rb +27 -0
- data/spec/lib/hubspot/deal_pipeline_spec.rb +4 -15
- data/spec/lib/hubspot/deal_properties_spec.rb +11 -58
- data/spec/lib/hubspot/deal_spec.rb +11 -53
- data/spec/lib/hubspot/engagement_spec.rb +20 -31
- data/spec/lib/hubspot/file_spec.rb +5 -30
- data/spec/lib/hubspot/form_spec.rb +36 -33
- data/spec/lib/hubspot/meeting_spec.rb +75 -0
- data/spec/spec_helper.rb +13 -4
- data/spec/support/vcr.rb +3 -6
- metadata +12 -24
- data/spec/lib/hubspot/topic_spec.rb +0 -23
- data/spec/support/tests_helper.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adea84341de555a5a7b9d83e03f8aa1013484015ad17d151f4876e9f2bd02293
|
4
|
+
data.tar.gz: 16380d38efaea5c290d2d3b969e76b7501f81beab80a2bec1b8dee6209c5bc57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ca148e0b2648da567d90d312cf979b1bcf8f840ed56393623d8c4cdb2aa0a7d1fe711721fd0828d5062837765280dc4f39719742cd124313bb9e15d31371e89
|
7
|
+
data.tar.gz: b3f6ac7fd1468a9caf227bd37f7cbe8316328ee88008e0305d891fa7c11478e9161425ababe9eb93416684284e39f2839f468e5667d6e9ce05e96c6c807b617c
|
data/README.md
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
# HubSpot REST API wrappers for ruby
|
2
2
|
|
3
|
-
**This is the master branch and contains unreleased and potentially breaking changes. If you are looking for the most recent stable release you want the [v0-stable branch](https://github.com/adimichele/hubspot-ruby/tree/v0-stable).**
|
4
|
-
|
5
3
|
Wraps the HubSpot REST API for convenient access from ruby applications.
|
6
4
|
|
7
5
|
Documentation for the HubSpot REST API can be found here: https://developers.hubspot.com/docs/endpoints
|
8
6
|
|
7
|
+
## Disclaimer
|
8
|
+
|
9
|
+
This gem is a fork of the unofficial [hubspot-ruby](https://github.com/HubspotCommunity/hubspot-ruby) gem which is unfortunately not maintained anymore.
|
10
|
+
|
11
|
+
The API has evolved quite a bit and while this is not a drop-in replacement you should feel familiar if you come from `hubspot-ruby`.
|
12
|
+
|
13
|
+
This project and the code therein was not created by and is not supported by HubSpot, Inc or any of its affiliates.
|
14
|
+
|
9
15
|
## Setup
|
10
16
|
|
11
17
|
gem install hubspot-api-ruby
|
@@ -141,15 +147,17 @@ By default, the VCR recording mode is set to `:none`, which allows recorded
|
|
141
147
|
requests to be re-played but raises for any new request. This prevents the test
|
142
148
|
suite from issuing unexpected HTTP requests.
|
143
149
|
|
144
|
-
|
145
|
-
environment variable:
|
150
|
+
Some requests require to be done on a live hubspot portal, you can set the `HUBSPOT_HAPI_KEY` environement variable, for example inside a `.env.test` file :
|
146
151
|
|
147
|
-
```
|
148
|
-
|
152
|
+
```
|
153
|
+
HUBSPOT_HAPI_KEY=xxxx
|
149
154
|
```
|
150
155
|
|
151
|
-
|
156
|
+
To add a new test or update a VCR recording, run the test with the `VCR_RECORD_MODE`
|
157
|
+
environment variable, for instance:
|
152
158
|
|
153
|
-
|
159
|
+
```sh
|
160
|
+
VCR_RECORD_MODE=new_episodes bundle exec rspec spec
|
161
|
+
```
|
154
162
|
|
155
|
-
|
163
|
+
[VCR]: https://github.com/vcr/vcr
|
data/hubspot-api-ruby.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "hubspot-api-ruby"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.9.0"
|
4
4
|
s.require_paths = ["lib"]
|
5
5
|
s.authors = ["Jonathan"]
|
6
6
|
s.email = ["jonathan@hoggo.com"]
|
@@ -10,10 +10,10 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.files += Dir["lib/**/*.rb"]
|
11
11
|
s.files += Dir["lib/**/*.rake"]
|
12
12
|
s.files += Dir["spec/**/*.rb"]
|
13
|
-
s.homepage = "
|
13
|
+
s.homepage = "https://github.com/captaincontrat/hubspot-api-ruby"
|
14
14
|
s.summary = "hubspot-api-ruby is a wrapper for the HubSpot REST API"
|
15
15
|
s.metadata = {
|
16
|
-
"changelog_uri" => "https://github.com/
|
16
|
+
"changelog_uri" => "https://github.com/captaincontrat/hubspot-api-ruby/blob/master/History.md"
|
17
17
|
}
|
18
18
|
|
19
19
|
s.required_ruby_version = ">= 2.3"
|
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_runtime_dependency "httparty", ">= 0.10"
|
24
24
|
|
25
25
|
# Add development-only dependencies here
|
26
|
-
s.add_development_dependency("appraisal", "~> 2.2")
|
27
26
|
s.add_development_dependency("dotenv")
|
28
27
|
s.add_development_dependency("rake", "~> 11.0")
|
29
28
|
s.add_development_dependency("rspec", "~> 3.8")
|
data/lib/hubspot/association.rb
CHANGED
@@ -1,80 +1,106 @@
|
|
1
1
|
class Hubspot::Association
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
COMPANY_TO_DEAL = 6
|
7
|
-
DEFINITION_TARGET_TO_CLASS = {
|
8
|
-
2 => Hubspot::Contact,
|
9
|
-
3 => Hubspot::Contact,
|
10
|
-
4 => Hubspot::Deal,
|
11
|
-
5 => Hubspot::Company,
|
12
|
-
6 => Hubspot::Deal
|
2
|
+
OBJECT_TARGET_TO_CLASS = {
|
3
|
+
"Contact" => Hubspot::Contact,
|
4
|
+
"Deal" => Hubspot::Deal,
|
5
|
+
"Company" => Hubspot::Company
|
13
6
|
}.freeze
|
14
7
|
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
ASSOCIATION_DEFINITIONS = {
|
9
|
+
"Company" => {
|
10
|
+
"Contact" => 2,
|
11
|
+
"Deal" => 6,
|
12
|
+
"Company" => 13
|
13
|
+
},
|
14
|
+
"Deal" => {
|
15
|
+
"Company" => 5,
|
16
|
+
"Contact" => 3
|
17
|
+
},
|
18
|
+
"Contact" => {
|
19
|
+
"Deal" => 4
|
20
|
+
}
|
21
|
+
}.freeze
|
18
22
|
|
19
23
|
class << self
|
20
|
-
def create(
|
21
|
-
batch_create([{
|
24
|
+
def create(object_type, object_id, to_object_type, to_object_id)
|
25
|
+
batch_create(object_type, to_object_type, [{from_id: object_id, to_id: to_object_id}])
|
22
26
|
end
|
23
27
|
|
24
28
|
# Make multiple associations in a single API call
|
25
|
-
# {https://developers.hubspot.com/docs/
|
29
|
+
# {https://developers.hubspot.com/docs/api/crm/associations}
|
26
30
|
# usage:
|
27
|
-
# Hubspot::Association.batch_create([{
|
28
|
-
def batch_create(associations)
|
29
|
-
|
30
|
-
|
31
|
+
# Hubspot::Association.batch_create("Company", "Contact", [{from_id: 1, to_id: 2}]])
|
32
|
+
def batch_create(from_object_type, to_object_type, associations)
|
33
|
+
definition_id = ASSOCIATION_DEFINITIONS.dig(from_object_type, to_object_type)
|
34
|
+
request = { inputs: associations.map { |assocation| build_create_association_body(assocation, definition_id) } }
|
35
|
+
response = Hubspot::Connection.post_json("/crm/v4/associations/#{from_object_type}/#{to_object_type}/batch/create", params: { no_parse: true }, body: request)
|
36
|
+
return false if response.parsed_response["errors"].present?
|
37
|
+
|
38
|
+
response.success?
|
31
39
|
end
|
32
40
|
|
33
|
-
def delete(
|
34
|
-
batch_delete([{from_id:
|
41
|
+
def delete(object_type, object_id, to_object_type, to_object_id)
|
42
|
+
batch_delete(object_type, to_object_type, [{from_id: object_id, to_id: to_object_id}])
|
35
43
|
end
|
36
44
|
|
37
45
|
# Remove multiple associations in a single API call
|
38
|
-
# {https://developers.hubspot.com/docs/
|
46
|
+
# {https://developers.hubspot.com/docs/api/crm/associations}
|
39
47
|
# usage:
|
40
|
-
# Hubspot::Association.batch_delete([{ from_id: 1, to_id: 2
|
41
|
-
def batch_delete(associations)
|
42
|
-
request =
|
43
|
-
Hubspot::Connection.
|
48
|
+
# Hubspot::Association.batch_delete("Company", "Contact", [{ from_id: 1, to_id: 2}])
|
49
|
+
def batch_delete(from_object_type, to_object_type, associations)
|
50
|
+
request = { inputs: build_delete_associations_body(associations) }
|
51
|
+
Hubspot::Connection.post_json("/crm/v4/associations/#{from_object_type}/#{to_object_type}/batch/archive", params: { no_parse: true }, body: request).success?
|
44
52
|
end
|
45
53
|
|
46
|
-
# Retrieve all associated resources given a source (
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# Hubspot::Association.all(42, Hubspot::Association::DEAL_TO_CONTACT)
|
54
|
-
def all(resource_id, definition_id)
|
55
|
-
opts = { resource_id: resource_id, definition_id: definition_id }
|
56
|
-
klass = DEFINITION_TARGET_TO_CLASS[definition_id]
|
57
|
-
raise(Hubspot::InvalidParams, 'Definition not supported') unless klass.present?
|
54
|
+
# Retrieve all associated resources given a source (object_type and object_id) and a relation type (to_object_type)
|
55
|
+
# {https://developers.hubspot.com/docs/api/crm/associations}
|
56
|
+
# Warning: it will return at most 1000 objects and make up to 1001 queries
|
57
|
+
# Hubspot::Association.all("Company", 42, "Contact")
|
58
|
+
def all(object_type, object_id, to_object_type)
|
59
|
+
klass = OBJECT_TARGET_TO_CLASS[to_object_type]
|
60
|
+
raise(Hubspot::InvalidParams, 'Object type not supported') unless klass.present?
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
response = Hubspot::Connection.get_json(ASSOCIATIONS_PATH, params)
|
62
|
-
|
63
|
-
resources = response['results'].map { |result| klass.find(result) }
|
64
|
-
[resources, response['offset'], response['has-more']]
|
65
|
-
end
|
66
|
-
collection.resources
|
62
|
+
response = Hubspot::Connection.get_json("/crm/v4/objects/#{object_type}/#{object_id}/associations/#{to_object_type}", {})
|
63
|
+
response['results'].map { |result| klass.find(result["toObjectId"]) }
|
67
64
|
end
|
68
65
|
|
69
66
|
private
|
70
67
|
|
71
|
-
def
|
68
|
+
def build_create_association_body(association, definition_id)
|
72
69
|
{
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
from: {
|
71
|
+
id: association[:from_id]
|
72
|
+
},
|
73
|
+
to: {
|
74
|
+
id: association[:to_id]
|
75
|
+
},
|
76
|
+
types: [
|
77
|
+
{
|
78
|
+
associationCategory: "HUBSPOT_DEFINED",
|
79
|
+
associationTypeId: definition_id
|
80
|
+
}
|
81
|
+
]
|
77
82
|
}
|
78
83
|
end
|
84
|
+
|
85
|
+
def build_delete_associations_body(associations)
|
86
|
+
normalized_associations = associations.inject({}) do |memo, association|
|
87
|
+
memo[association[:from_id]] ||= []
|
88
|
+
memo[association[:from_id]] << association[:to_id]
|
89
|
+
memo
|
90
|
+
end
|
91
|
+
|
92
|
+
normalized_associations.map do |from_id, to_ids|
|
93
|
+
{
|
94
|
+
from: {
|
95
|
+
id: from_id
|
96
|
+
},
|
97
|
+
to: to_ids.map do |to_id|
|
98
|
+
{
|
99
|
+
id: to_id
|
100
|
+
}
|
101
|
+
end
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
79
105
|
end
|
80
106
|
end
|
data/lib/hubspot/company.rb
CHANGED
@@ -78,11 +78,11 @@ class Hubspot::Company < Hubspot::Resource
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def add_contact(id, contact_id)
|
81
|
-
Hubspot::Association.create(id,
|
81
|
+
Hubspot::Association.create("Company", id, "Contact", contact_id)
|
82
82
|
end
|
83
83
|
|
84
84
|
def remove_contact(id, contact_id)
|
85
|
-
Hubspot::Association.delete(id,
|
85
|
+
Hubspot::Association.delete("Company", id, "Contact", contact_id)
|
86
86
|
end
|
87
87
|
|
88
88
|
def batch_update(companies, opts = {})
|
data/lib/hubspot/config.rb
CHANGED
@@ -5,7 +5,7 @@ module Hubspot
|
|
5
5
|
class Config
|
6
6
|
CONFIG_KEYS = [
|
7
7
|
:hapikey, :base_url, :portal_id, :logger, :access_token, :client_id,
|
8
|
-
:client_secret, :redirect_uri, :read_timeout, :open_timeout
|
8
|
+
:client_secret, :redirect_uri, :read_timeout, :open_timeout, :custom_event_prefix
|
9
9
|
]
|
10
10
|
DEFAULT_LOGGER = Logger.new(nil)
|
11
11
|
DEFAULT_BASE_URL = "https://api.hubapi.com".freeze
|
@@ -15,16 +15,17 @@ module Hubspot
|
|
15
15
|
|
16
16
|
def configure(config)
|
17
17
|
config.stringify_keys!
|
18
|
-
@hapikey = config[
|
19
|
-
@base_url = config[
|
20
|
-
@portal_id = config[
|
21
|
-
@logger = config[
|
22
|
-
@access_token = config[
|
23
|
-
@client_id = config[
|
24
|
-
@client_secret = config[
|
25
|
-
@redirect_uri = config[
|
18
|
+
@hapikey = config['hapikey']
|
19
|
+
@base_url = config['base_url'] || DEFAULT_BASE_URL
|
20
|
+
@portal_id = config['portal_id']
|
21
|
+
@logger = config['logger'] || DEFAULT_LOGGER
|
22
|
+
@access_token = config['access_token']
|
23
|
+
@client_id = config['client_id'] if config['client_id'].present?
|
24
|
+
@client_secret = config['client_secret'] if config['client_secret'].present?
|
25
|
+
@redirect_uri = config['redirect_uri'] if config['redirect_uri'].present?
|
26
26
|
@read_timeout = config['read_timeout'] || config['timeout']
|
27
27
|
@open_timeout = config['open_timeout'] || config['timeout']
|
28
|
+
@custom_event_prefix = config['custom_event_prefix']
|
28
29
|
|
29
30
|
unless authentication_uncertain?
|
30
31
|
raise Hubspot::ConfigurationError.new("You must provide either an access_token or an hapikey")
|
data/lib/hubspot/connection.rb
CHANGED
@@ -7,7 +7,7 @@ module Hubspot
|
|
7
7
|
url = generate_url(path, opts)
|
8
8
|
response = get(url, format: :json, read_timeout: read_timeout(opts), open_timeout: open_timeout(opts))
|
9
9
|
log_request_and_response url, response
|
10
|
-
handle_response(response)
|
10
|
+
handle_response(response).parsed_response
|
11
11
|
end
|
12
12
|
|
13
13
|
def post_json(path, opts)
|
@@ -24,9 +24,9 @@ module Hubspot
|
|
24
24
|
)
|
25
25
|
|
26
26
|
log_request_and_response url, response, opts[:body]
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
handle_response(response).yield_self do |r|
|
28
|
+
no_parse ? r : r.parsed_response
|
29
|
+
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def put_json(path, options)
|
@@ -43,17 +43,16 @@ module Hubspot
|
|
43
43
|
)
|
44
44
|
|
45
45
|
log_request_and_response(url, response, options[:body])
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
handle_response(response).yield_self do |r|
|
47
|
+
no_parse ? r : r.parsed_response
|
48
|
+
end
|
49
49
|
end
|
50
50
|
|
51
51
|
def delete_json(path, opts)
|
52
52
|
url = generate_url(path, opts)
|
53
53
|
response = delete(url, format: :json, read_timeout: read_timeout(opts), open_timeout: open_timeout(opts))
|
54
54
|
log_request_and_response url, response, opts[:body]
|
55
|
-
|
56
|
-
response
|
55
|
+
handle_response(response)
|
57
56
|
end
|
58
57
|
|
59
58
|
protected
|
@@ -67,11 +66,10 @@ module Hubspot
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def handle_response(response)
|
70
|
-
if response.success?
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
69
|
+
return response if response.success?
|
70
|
+
|
71
|
+
raise(Hubspot::NotFoundError.new(response)) if response.not_found?
|
72
|
+
raise(Hubspot::RequestError.new(response))
|
75
73
|
end
|
76
74
|
|
77
75
|
def log_request_and_response(uri, response, body=nil)
|
@@ -149,4 +147,12 @@ module Hubspot
|
|
149
147
|
get(url, body: opts[:body], headers: opts[:headers])
|
150
148
|
end
|
151
149
|
end
|
150
|
+
|
151
|
+
class CustomEventConnection < Connection
|
152
|
+
def self.trigger(path, opts)
|
153
|
+
url = generate_url(path, opts[:params], { hapikey: true })
|
154
|
+
headers = (opts[:headers] || {}).merge('content-type': 'application/json')
|
155
|
+
post(url, body: opts[:body].to_json, headers: headers)
|
156
|
+
end
|
157
|
+
end
|
152
158
|
end
|
data/lib/hubspot/contact.rb
CHANGED
@@ -12,7 +12,6 @@ class Hubspot::Contact < Hubspot::Resource
|
|
12
12
|
MERGE_PATH = '/contacts/v1/contact/merge-vids/:id/'
|
13
13
|
SEARCH_PATH = '/contacts/v1/search/query'
|
14
14
|
UPDATE_PATH = '/contacts/v1/contact/vid/:id/profile'
|
15
|
-
UPDATE_PATH = '/contacts/v1/contact/vid/:id/profile'
|
16
15
|
BATCH_UPDATE_PATH = '/contacts/v1/contact/batch'
|
17
16
|
|
18
17
|
class << self
|
@@ -28,6 +27,11 @@ class Hubspot::Contact < Hubspot::Resource
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
30
|
+
def find_by_vid(vid)
|
31
|
+
response = Hubspot::Connection.get_json(FIND_PATH, id: vid)
|
32
|
+
from_result(response)
|
33
|
+
end
|
34
|
+
|
31
35
|
def find_by_email(email)
|
32
36
|
response = Hubspot::Connection.get_json(FIND_BY_EMAIL_PATH, email: email)
|
33
37
|
from_result(response)
|
data/lib/hubspot/contact_list.rb
CHANGED
@@ -10,7 +10,6 @@ module Hubspot
|
|
10
10
|
RECENT_CONTACTS_PATH = LIST_PATH + '/contacts/recent'
|
11
11
|
ADD_CONTACT_PATH = LIST_PATH + '/add'
|
12
12
|
REMOVE_CONTACT_PATH = LIST_PATH + '/remove'
|
13
|
-
REFRESH_PATH = LIST_PATH + '/refresh'
|
14
13
|
|
15
14
|
class << self
|
16
15
|
# {http://developers.hubspot.com/docs/methods/lists/create_list}
|
@@ -92,12 +91,6 @@ module Hubspot
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
95
|
-
# {http://developers.hubspot.com/docs/methods/lists/refresh_list}
|
96
|
-
def refresh
|
97
|
-
response = Hubspot::Connection.post_json(REFRESH_PATH, params: { list_id: @id, no_parse: true }, body: {})
|
98
|
-
response.code == 204
|
99
|
-
end
|
100
|
-
|
101
94
|
# {http://developers.hubspot.com/docs/methods/lists/add_contact_to_list}
|
102
95
|
def add(contacts)
|
103
96
|
contact_ids = [contacts].flatten.uniq.compact.map(&:id)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'hubspot/utils'
|
2
|
+
|
3
|
+
module Hubspot
|
4
|
+
#
|
5
|
+
# HubSpot Custom Behavioral Events HTTP API
|
6
|
+
#
|
7
|
+
# {https://developers.hubspot.com/docs/api/analytics/events}
|
8
|
+
#
|
9
|
+
class CustomEvent
|
10
|
+
POST_EVENT_PATH = '/events/v3/send'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def trigger(event_name, email, properties, options = {})
|
14
|
+
options[:params] ||= {}
|
15
|
+
options[:body] ||= {}
|
16
|
+
options[:body].merge!(
|
17
|
+
eventName: "#{Hubspot::Config.custom_event_prefix}_#{event_name}",
|
18
|
+
email: email,
|
19
|
+
properties: properties
|
20
|
+
)
|
21
|
+
Hubspot::CustomEventConnection.trigger(POST_EVENT_PATH, options).success?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/hubspot/deal.rb
CHANGED
@@ -64,13 +64,23 @@ module Hubspot
|
|
64
64
|
# Usage
|
65
65
|
# Hubspot::Deal.associate!(45146940, [32], [52])
|
66
66
|
def associate!(deal_id, company_ids=[], vids=[])
|
67
|
-
associations = company_ids.map do |id|
|
68
|
-
{ from_id: deal_id, to_id: id
|
67
|
+
company_associations = associations = company_ids.map do |id|
|
68
|
+
{ from_id: deal_id, to_id: id }
|
69
69
|
end
|
70
|
-
|
71
|
-
|
70
|
+
|
71
|
+
contact_associations = vids.map do |id|
|
72
|
+
{ from_id: deal_id, to_id: id}
|
73
|
+
end
|
74
|
+
|
75
|
+
results = []
|
76
|
+
if company_associations.any?
|
77
|
+
results << HubSpot::Association.batch_create("Deal", "Company", company_associations)
|
72
78
|
end
|
73
|
-
|
79
|
+
if contact_associations.any?
|
80
|
+
results << HubSpot::Association.batch_create("Deal", "Contact", contact_associations)
|
81
|
+
end
|
82
|
+
|
83
|
+
results.all?
|
74
84
|
end
|
75
85
|
|
76
86
|
# Didssociate a deal with a contact or company
|
@@ -78,13 +88,23 @@ module Hubspot
|
|
78
88
|
# Usage
|
79
89
|
# Hubspot::Deal.dissociate!(45146940, [32], [52])
|
80
90
|
def dissociate!(deal_id, company_ids=[], vids=[])
|
81
|
-
|
82
|
-
{ from_id: deal_id, to_id: id
|
91
|
+
company_associations = company_ids.map do |id|
|
92
|
+
{ from_id: deal_id, to_id: id }
|
83
93
|
end
|
84
|
-
|
85
|
-
|
94
|
+
|
95
|
+
contact_associations = vids.map do |id|
|
96
|
+
{ from_id: deal_id, to_id: id }
|
97
|
+
end
|
98
|
+
|
99
|
+
results = []
|
100
|
+
if company_associations.any?
|
101
|
+
results << HubSpot::Association.batch_delete("Deal", "Company", company_associations)
|
86
102
|
end
|
87
|
-
|
103
|
+
if contact_associations.any?
|
104
|
+
results << HubSpot::Association.batch_delete("Deal", "Contact", contact_associations)
|
105
|
+
end
|
106
|
+
|
107
|
+
results.all?
|
88
108
|
end
|
89
109
|
|
90
110
|
def find(deal_id)
|
@@ -134,12 +154,12 @@ module Hubspot
|
|
134
154
|
# @param object [Hubspot::Contact || Hubspot::Company] a contact or company
|
135
155
|
# @return [Array] Array of Hubspot::Deal records
|
136
156
|
def find_by_association(object)
|
137
|
-
|
138
|
-
when Hubspot::Company then
|
139
|
-
when Hubspot::Contact then
|
157
|
+
to_object_type = case object
|
158
|
+
when Hubspot::Company then "Company"
|
159
|
+
when Hubspot::Contact then "Contact"
|
140
160
|
else raise(Hubspot::InvalidParams, 'Instance type not supported')
|
141
161
|
end
|
142
|
-
Hubspot::Association.all(object.id,
|
162
|
+
Hubspot::Association.all(to_object_type, object.id, "Deal")
|
143
163
|
end
|
144
164
|
end
|
145
165
|
|
data/lib/hubspot/exceptions.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'hubspot/utils'
|
2
|
+
|
3
|
+
module Hubspot
|
4
|
+
class Meeting
|
5
|
+
#
|
6
|
+
# HubSpot Meeting API
|
7
|
+
#
|
8
|
+
# {https://developers.hubspot.com/docs/api/crm/meetings}
|
9
|
+
#
|
10
|
+
CREATE_MEETING_PATH = '/crm/v3/objects/meetings'
|
11
|
+
MEETING_PATH = '/crm/v3/objects/meetings/:meeting_id'
|
12
|
+
ASSOCIATE_MEETING_PATH = '/crm/v3/objects/meetings/:meeting_id/associations/Contact/:contact_id/meeting_event_to_contact'
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def create!(owner_id, meeting_title, meeting_body, start_date_time, end_date_time)
|
16
|
+
body = {
|
17
|
+
properties: {
|
18
|
+
hs_timestamp: DateTime.now.strftime('%Q'),
|
19
|
+
hubspot_owner_id: owner_id,
|
20
|
+
hs_meeting_title: meeting_title,
|
21
|
+
hs_meeting_body: meeting_body,
|
22
|
+
hs_meeting_start_time: start_date_time.is_a?(DateTime) ? start_date_time.strftime('%Q') : start_date_time,
|
23
|
+
hs_meeting_end_time: end_date_time.is_a?(DateTime) ? end_date_time.strftime('%Q') : end_date_time,
|
24
|
+
hs_meeting_outcome: 'SCHEDULED'
|
25
|
+
}
|
26
|
+
}
|
27
|
+
response = Hubspot::Connection.post_json(CREATE_MEETING_PATH, params: {}, body: body)
|
28
|
+
HashWithIndifferentAccess.new(response)
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy!(meeting_id)
|
32
|
+
Hubspot::Connection.delete_json(MEETING_PATH, {meeting_id: meeting_id})
|
33
|
+
end
|
34
|
+
|
35
|
+
def associate!(meeting_id, contact_id)
|
36
|
+
Hubspot::Connection.put_json(ASSOCIATE_MEETING_PATH,
|
37
|
+
params: {
|
38
|
+
meeting_id: meeting_id,
|
39
|
+
contact_id: contact_id
|
40
|
+
})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/hubspot/properties.rb
CHANGED
@@ -97,7 +97,7 @@ module Hubspot
|
|
97
97
|
|
98
98
|
def valid_group_params(params)
|
99
99
|
return {} if params.blank?
|
100
|
-
result = params.slice(*PROPERTY_SPECS[:group_field_names])
|
100
|
+
result = params.with_indifferent_access.slice(*PROPERTY_SPECS[:group_field_names])
|
101
101
|
result['properties'] = valid_property_params(result['properties']) unless result['properties'].blank?
|
102
102
|
result
|
103
103
|
end
|
data/lib/hubspot-api-ruby.rb
CHANGED
@@ -14,6 +14,7 @@ require 'hubspot/contact'
|
|
14
14
|
require 'hubspot/contact_properties'
|
15
15
|
require 'hubspot/contact_list'
|
16
16
|
require 'hubspot/event'
|
17
|
+
require 'hubspot/custom_event'
|
17
18
|
require 'hubspot/form'
|
18
19
|
require 'hubspot/blog'
|
19
20
|
require 'hubspot/topic'
|
@@ -27,6 +28,7 @@ require 'hubspot/engagement'
|
|
27
28
|
require 'hubspot/subscription'
|
28
29
|
require 'hubspot/oauth'
|
29
30
|
require 'hubspot/file'
|
31
|
+
require 'hubspot/meeting'
|
30
32
|
|
31
33
|
module Hubspot
|
32
34
|
def self.configure(config={})
|