forked from lounna-team/hubspot-api-ruby
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Make most specs pass * Update Hubspot::Association to use v4 API as v1 is buggy * Run actions on all branches * Pass secrets * Test again ruby 3.1 and rails 7.9 * Clean up dead constants * Add association definition for company-to-company association * Introduce NotFoundError to differentiate a 404 from any other issue * Code review
- Loading branch information
Showing
288 changed files
with
30,475 additions
and
257,732 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,7 +51,7 @@ tmp | |
*.sublime-workspace | ||
|
||
# Ignore local environment variables | ||
/.env | ||
/.env* | ||
|
||
# Byebug history | ||
.byebug_history |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
source 'https://rubygems.org' | ||
|
||
gem "activesupport", "~> 7.0.3" | ||
gemspec path: '../' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,106 @@ | ||
class Hubspot::Association | ||
COMPANY_TO_CONTACT = 2 | ||
DEAL_TO_CONTACT = 3 | ||
CONTACT_TO_DEAL = 4 | ||
DEAL_TO_COMPANY = 5 | ||
COMPANY_TO_DEAL = 6 | ||
DEFINITION_TARGET_TO_CLASS = { | ||
2 => Hubspot::Contact, | ||
3 => Hubspot::Contact, | ||
4 => Hubspot::Deal, | ||
5 => Hubspot::Company, | ||
6 => Hubspot::Deal | ||
OBJECT_TARGET_TO_CLASS = { | ||
"Contact" => Hubspot::Contact, | ||
"Deal" => Hubspot::Deal, | ||
"Company" => Hubspot::Company | ||
}.freeze | ||
|
||
BATCH_CREATE_PATH = '/crm-associations/v1/associations/create-batch' | ||
BATCH_DELETE_PATH = '/crm-associations/v1/associations/delete-batch' | ||
ASSOCIATIONS_PATH = '/crm-associations/v1/associations/:resource_id/HUBSPOT_DEFINED/:definition_id' | ||
ASSOCIATION_DEFINITIONS = { | ||
"Company" => { | ||
"Contact" => 2, | ||
"Deal" => 6, | ||
"Company" => 13 | ||
}, | ||
"Deal" => { | ||
"Company" => 5, | ||
"Contact" => 3 | ||
}, | ||
"Contact" => { | ||
"Deal" => 4 | ||
} | ||
}.freeze | ||
|
||
class << self | ||
def create(from_id, to_id, definition_id) | ||
batch_create([{ from_id: from_id, to_id: to_id, definition_id: definition_id }]) | ||
def create(object_type, object_id, to_object_type, to_object_id) | ||
batch_create(object_type, to_object_type, [{from_id: object_id, to_id: to_object_id}]) | ||
end | ||
|
||
# Make multiple associations in a single API call | ||
# {https://developers.hubspot.com/docs/methods/crm-associations/batch-associate-objects} | ||
# {https://developers.hubspot.com/docs/api/crm/associations} | ||
# usage: | ||
# Hubspot::Association.batch_create([{ from_id: 1, to_id: 2, definition_id: Hubspot::Association::COMPANY_TO_CONTACT }]) | ||
def batch_create(associations) | ||
request = associations.map { |assocation| build_association_body(assocation) } | ||
Hubspot::Connection.put_json(BATCH_CREATE_PATH, params: { no_parse: true }, body: request).success? | ||
# Hubspot::Association.batch_create("Company", "Contact", [{from_id: 1, to_id: 2}]]) | ||
def batch_create(from_object_type, to_object_type, associations) | ||
definition_id = ASSOCIATION_DEFINITIONS.dig(from_object_type, to_object_type) | ||
request = { inputs: associations.map { |assocation| build_create_association_body(assocation, definition_id) } } | ||
response = Hubspot::Connection.post_json("/crm/v4/associations/#{from_object_type}/#{to_object_type}/batch/create", params: { no_parse: true }, body: request) | ||
return false if response.parsed_response["errors"].present? | ||
|
||
response.success? | ||
end | ||
|
||
def delete(from_id, to_id, definition_id) | ||
batch_delete([{from_id: from_id, to_id: to_id, definition_id: definition_id}]) | ||
def delete(object_type, object_id, to_object_type, to_object_id) | ||
batch_delete(object_type, to_object_type, [{from_id: object_id, to_id: to_object_id}]) | ||
end | ||
|
||
# Remove multiple associations in a single API call | ||
# {https://developers.hubspot.com/docs/methods/crm-associations/batch-delete-associations} | ||
# {https://developers.hubspot.com/docs/api/crm/associations} | ||
# usage: | ||
# Hubspot::Association.batch_delete([{ from_id: 1, to_id: 2, definition_id: Hubspot::Association::COMPANY_TO_CONTACT }]) | ||
def batch_delete(associations) | ||
request = associations.map { |assocation| build_association_body(assocation) } | ||
Hubspot::Connection.put_json(BATCH_DELETE_PATH, params: { no_parse: true }, body: request).success? | ||
# Hubspot::Association.batch_delete("Company", "Contact", [{ from_id: 1, to_id: 2}]) | ||
def batch_delete(from_object_type, to_object_type, associations) | ||
request = { inputs: build_delete_associations_body(associations) } | ||
Hubspot::Connection.post_json("/crm/v4/associations/#{from_object_type}/#{to_object_type}/batch/archive", params: { no_parse: true }, body: request).success? | ||
end | ||
|
||
# Retrieve all associated resources given a source (resource_id) and a kind (definition_id) | ||
# Example: if resource_id is a deal, using DEAL_TO_CONTACT will find every contact associated with the deal | ||
# {https://developers.hubspot.com/docs/methods/crm-associations/get-associations} | ||
# Warning: it will make N+M queries, where | ||
# N is the number of PagedCollection requests necessary to get all ids, | ||
# and M is the number of results, each resulting in a find | ||
# usage: | ||
# Hubspot::Association.all(42, Hubspot::Association::DEAL_TO_CONTACT) | ||
def all(resource_id, definition_id) | ||
opts = { resource_id: resource_id, definition_id: definition_id } | ||
klass = DEFINITION_TARGET_TO_CLASS[definition_id] | ||
raise(Hubspot::InvalidParams, 'Definition not supported') unless klass.present? | ||
# Retrieve all associated resources given a source (object_type and object_id) and a relation type (to_object_type) | ||
# {https://developers.hubspot.com/docs/api/crm/associations} | ||
# Warning: it will return at most 1000 objects and make up to 1001 queries | ||
# Hubspot::Association.all("Company", 42, "Contact") | ||
def all(object_type, object_id, to_object_type) | ||
klass = OBJECT_TARGET_TO_CLASS[to_object_type] | ||
raise(Hubspot::InvalidParams, 'Object type not supported') unless klass.present? | ||
|
||
collection = Hubspot::PagedCollection.new(opts) do |options, offset, limit| | ||
params = options.merge(offset: offset, limit: limit) | ||
response = Hubspot::Connection.get_json(ASSOCIATIONS_PATH, params) | ||
|
||
resources = response['results'].map { |result| klass.find(result) } | ||
[resources, response['offset'], response['has-more']] | ||
end | ||
collection.resources | ||
response = Hubspot::Connection.get_json("/crm/v4/objects/#{object_type}/#{object_id}/associations/#{to_object_type}", {}) | ||
response['results'].map { |result| klass.find(result["toObjectId"]) } | ||
end | ||
|
||
private | ||
|
||
def build_association_body(assocation) | ||
def build_create_association_body(association, definition_id) | ||
{ | ||
fromObjectId: assocation[:from_id], | ||
toObjectId: assocation[:to_id], | ||
category: 'HUBSPOT_DEFINED', | ||
definitionId: assocation[:definition_id] | ||
from: { | ||
id: association[:from_id] | ||
}, | ||
to: { | ||
id: association[:to_id] | ||
}, | ||
types: [ | ||
{ | ||
associationCategory: "HUBSPOT_DEFINED", | ||
associationTypeId: definition_id | ||
} | ||
] | ||
} | ||
end | ||
|
||
def build_delete_associations_body(associations) | ||
normalized_associations = associations.inject({}) do |memo, association| | ||
memo[association[:from_id]] ||= [] | ||
memo[association[:from_id]] << association[:to_id] | ||
memo | ||
end | ||
|
||
normalized_associations.map do |from_id, to_ids| | ||
{ | ||
from: { | ||
id: from_id | ||
}, | ||
to: to_ids.map do |to_id| | ||
{ | ||
id: to_id | ||
} | ||
end | ||
} | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.