hubspot-ruby 0.2.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16ee939bb4d593cc623309e093902d9a937b9fda
4
- data.tar.gz: d5c6b6765d4a3a7adda09fbb6b9a1768c91b1d86
3
+ metadata.gz: 9eded4f33457d91f6b5feb303f5bd7524223d8ab
4
+ data.tar.gz: 84a6116a408d19dd093ebd40d0fae9d535e5e078
5
5
  SHA512:
6
- metadata.gz: 6f22e580fac3d5a5f4b1ac812cf21040c6105e8fc86ad4e03dc71b0aa0276bf48f4b89cf826d806eb2a7cef5be90a820c47a81a23ca27d34833bdf77a4076dfe
7
- data.tar.gz: d322208c51497e956f63d9cb7453ce90540691af81661bcea456ca3118deb53da6fcb95a9ecd8a91f2dc433a12a47a482bb2eec1fd7043a12e7fd27ef425c32c
6
+ metadata.gz: f3359f3aeef879c07870f8d6537f99c7d96117224e13ebbb6a1a87032aaa2ba212f5862dcbde1795cf2feefb01850d2b3879dc48e96672f55bab8e1c43be3e6a
7
+ data.tar.gz: 350179721426bffbd0260655aa98485b855591042dc8edffb4e4139b70390bad24512d67a27af1de0313741926b782b3133cd822f1df7164677f223a176d1929
data/README.md CHANGED
@@ -37,6 +37,12 @@ Here's what you can do for now:
37
37
  Hubspot::Contact.create!("email@address.com", {firstname: "First", lastname: "Last"})
38
38
  ```
39
39
 
40
+ #### In batches
41
+
42
+ ```ruby
43
+ Hubspot::Contact.create_or_update!([{email: 'smith@example.com', firstname: 'First', lastname: 'Last'}])
44
+ ```
45
+
40
46
  ### Find a contact
41
47
 
42
48
  These methods will return a `Hubspot::Contact` object if successful, `nil` otherwise:
@@ -54,6 +60,11 @@ Given an instance of `Hubspot::Contact`, update its attributes with:
54
60
  contact.update!({firstname: "First", lastname: "Last"})
55
61
  ```
56
62
 
63
+ #### In batches
64
+
65
+ ```ruby
66
+ Hubspot::Contact.create_or_update!([{vid: '12345', firstname: 'First', lastname: 'Last'}])
67
+ ```
57
68
  ## Contributing to hubspot-ruby
58
69
 
59
70
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
@@ -1,11 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "hubspot-ruby"
3
- s.version = "0.2.0"
3
+ s.version = "0.2.1"
4
4
  s.require_paths = ["lib"]
5
5
  s.authors = ["Andrew DiMichele"]
6
6
  s.description = "hubspot-ruby is a wrapper for the HubSpot REST API"
7
7
  s.files = [".rspec", "Gemfile", "Gemfile.lock", "Guardfile", "LICENSE.txt", "README.md", "RELEASING.md", "Rakefile", "hubspot-ruby.gemspec"]
8
8
  s.files += Dir["lib/**/*.rb"]
9
+ s.files += Dir["lib/**/*.rake"]
9
10
  s.files += Dir["spec/**/*.rb"]
10
11
  s.homepage = "http://github.com/adimichele/hubspot-ruby"
11
12
  s.summary = "hubspot-ruby is a wrapper for the HubSpot REST API"
@@ -68,7 +68,7 @@ module Hubspot
68
68
  v.is_a?(Array) ? v.map { |value| param_string(k,value) } : param_string(k,v)
69
69
  end.join("&")
70
70
 
71
- path += "?" if query.present?
71
+ p path += path.include?('?') ? '&' : "?" if query.present?
72
72
  base_url + path + query
73
73
  end
74
74
 
@@ -6,19 +6,20 @@ module Hubspot
6
6
  #
7
7
  # TODO: work on all endpoints that can specify contact properties, property mode etc... as params. cf pending specs
8
8
  class Contact
9
- CREATE_CONTACT_PATH = '/contacts/v1/contact'
10
- GET_CONTACT_BY_EMAIL_PATH = '/contacts/v1/contact/email/:contact_email/profile'
11
- GET_CONTACTS_BY_EMAIL_PATH = '/contacts/v1/contact/emails/batch'
12
- GET_CONTACT_BY_ID_PATH = '/contacts/v1/contact/vid/:contact_id/profile'
13
- CONTACT_BATCH_PATH = '/contacts/v1/contact/vids/batch'
14
- GET_CONTACT_BY_UTK_PATH = '/contacts/v1/contact/utk/:contact_utk/profile'
15
- GET_CONTACTS_BY_UTK_PATH = '/contacts/v1/contact/utks/batch'
16
- UPDATE_CONTACT_PATH = '/contacts/v1/contact/vid/:contact_id/profile'
17
- DESTROY_CONTACT_PATH = '/contacts/v1/contact/vid/:contact_id'
18
- CONTACTS_PATH = '/contacts/v1/lists/all/contacts/all'
19
- RECENT_CONTACTS_PATH = '/contacts/v1/lists/recently_updated/contacts/recent'
20
- CREATE_OR_UPDATE_PATH = '/contacts/v1/contact/createOrUpdate/email/:contact_email'
21
- QUERY_PATH = '/contacts/v1/search/query'
9
+ CREATE_CONTACT_PATH = '/contacts/v1/contact'
10
+ BATCH_CREATE_OR_UPDATE_PATH = '/contacts/v1/contact/batch/'
11
+ GET_CONTACT_BY_EMAIL_PATH = '/contacts/v1/contact/email/:contact_email/profile'
12
+ GET_CONTACTS_BY_EMAIL_PATH = '/contacts/v1/contact/emails/batch'
13
+ GET_CONTACT_BY_ID_PATH = '/contacts/v1/contact/vid/:contact_id/profile'
14
+ CONTACT_BATCH_PATH = '/contacts/v1/contact/vids/batch'
15
+ GET_CONTACT_BY_UTK_PATH = '/contacts/v1/contact/utk/:contact_utk/profile'
16
+ GET_CONTACTS_BY_UTK_PATH = '/contacts/v1/contact/utks/batch'
17
+ UPDATE_CONTACT_PATH = '/contacts/v1/contact/vid/:contact_id/profile'
18
+ DESTROY_CONTACT_PATH = '/contacts/v1/contact/vid/:contact_id'
19
+ CONTACTS_PATH = '/contacts/v1/lists/all/contacts/all'
20
+ RECENT_CONTACTS_PATH = '/contacts/v1/lists/recently_updated/contacts/recent'
21
+ CREATE_OR_UPDATE_PATH = '/contacts/v1/contact/createOrUpdate/email/:contact_email'
22
+ QUERY_PATH = '/contacts/v1/search/query'
22
23
 
23
24
  class << self
24
25
  # {https://developers.hubspot.com/docs/methods/contacts/create_contact}
@@ -47,7 +48,6 @@ module Hubspot
47
48
  # TODO: create or update a contact
48
49
  # PATH /contacts/v1/contact/createOrUpdate/email/:contact_email
49
50
  # API endpoint: https://developers.hubspot.com/docs/methods/contacts/create_or_update
50
- # + batch mode: https://developers.hubspot.com/docs/methods/contacts/batch_create_or_update
51
51
  def createOrUpdate(email, params={})
52
52
  post_data = {properties: Hubspot::Utils.hash_to_properties(params.stringify_keys)}
53
53
  response = Hubspot::Connection.post_json(CREATE_OR_UPDATE_PATH, params: { contact_email: email }, body: post_data )
@@ -56,6 +56,28 @@ module Hubspot
56
56
  contact
57
57
  end
58
58
 
59
+ # NOTE: Performance is best when calls are limited to 100 or fewer contacts
60
+ # {https://developers.hubspot.com/docs/methods/contacts/batch_create_or_update}
61
+ def create_or_update!(contacts)
62
+ query = contacts.map do |ch|
63
+ contact_hash = ch.with_indifferent_access
64
+ contact_param = {
65
+ properties: Hubspot::Utils.hash_to_properties(contact_hash.except(:vid))
66
+ }
67
+ if contact_hash[:vid]
68
+ contact_param.merge!(vid: contact_hash[:vid])
69
+ elsif contact_hash[:email]
70
+ contact_param.merge!(email: contact_hash[:email])
71
+ else
72
+ raise Hubspot::InvalidParams, 'expecting vid or email for contact'
73
+ end
74
+ contact_param
75
+ end
76
+ Hubspot::Connection.post_json(BATCH_CREATE_OR_UPDATE_PATH,
77
+ params: {},
78
+ body: query)
79
+ end
80
+
59
81
  # NOTE: problem with batch api endpoint
60
82
  # {https://developers.hubspot.com/docs/methods/contacts/get_contact}
61
83
  # {https://developers.hubspot.com/docs/methods/contacts/get_batch_by_vid}
@@ -11,6 +11,7 @@ module Hubspot
11
11
  DEAL_PATH = "/deals/v1/deal/:deal_id"
12
12
  RECENT_UPDATED_PATH = "/deals/v1/deal/recent/modified"
13
13
  UPDATE_DEAL_PATH = '/deals/v1/deal/:deal_id'
14
+ ASSOCIATE_DEAL_PATH = '/deals/v1/deal/:deal_id/associations/:OBJECTTYPE?id=:objectId'
14
15
 
15
16
  attr_reader :properties
16
17
  attr_reader :portal_id
@@ -36,6 +37,17 @@ module Hubspot
36
37
  new(response)
37
38
  end
38
39
 
40
+ # Associate a deal with a contact or company
41
+ # {http://developers.hubspot.com/docs/methods/deals/associate_deal}
42
+ # Usage
43
+ # Hubspot::Deal.associate!(45146940, [], [52])
44
+ def associate!(deal_id, company_ids=[], vids=[])
45
+ objecttype = company_ids.any? ? 'COMPANY' : 'CONTACT'
46
+ object_ids = (company_ids.any? ? company_ids : vids).join('&id=')
47
+ Hubspot::Connection.put_json(ASSOCIATE_DEAL_PATH, params: { deal_id: deal_id, OBJECTTYPE: objecttype, objectId: object_ids}, body: {})
48
+ end
49
+
50
+
39
51
  def find(deal_id)
40
52
  response = Hubspot::Connection.get_json(DEAL_PATH, { deal_id: deal_id })
41
53
  new(response)
@@ -0,0 +1,49 @@
1
+ require 'hubspot-ruby'
2
+
3
+ namespace :hubspot do
4
+ desc 'Dump properties to file'
5
+ task :dump_properties, [:kind, :file, :hapikey, :include, :exclude] do |_, args|
6
+ hapikey = args[:hapikey] || ENV['HUBSPOT_API_KEY']
7
+ kind = args[:kind]
8
+ unless %w(contact deal).include?(kind)
9
+ raise ArgumentError, ':kind must be either "contact" or "deal"'
10
+ end
11
+ klass = kind == 'contact' ? Hubspot::ContactProperties : Hubspot::DealProperties
12
+ props = Hubspot::Utils::dump_properties(klass, hapikey, build_filter(args))
13
+ if args[:file].blank?
14
+ puts JSON.pretty_generate(props)
15
+ else
16
+ File.open(args[:file], 'w') do |f|
17
+ f.write(JSON.pretty_generate(props))
18
+ end
19
+ end
20
+ end
21
+
22
+ desc 'Restore properties from file'
23
+ task :restore_properties, [:kind, :file, :hapikey, :dry_run] do |_, args|
24
+ hapikey = args[:hapikey] || ENV['HUBSPOT_API_KEY']
25
+ if args[:file].blank?
26
+ raise ArgumentError, ':file is a required parameter'
27
+ end
28
+ kind = args[:kind]
29
+ unless %w(contact deal).include?(kind)
30
+ raise ArgumentError, ':kind must be either "contact" or "deal"'
31
+ end
32
+ klass = kind == 'contact' ? Hubspot::ContactProperties : Hubspot::DealProperties
33
+ file = File.read(args[:file])
34
+ props = JSON.parse(file)
35
+ Hubspot::Utils.restore_properties(klass, hapikey, props, args[:dry_run] != 'false')
36
+ end
37
+
38
+ private
39
+
40
+ def build_filter(args)
41
+ { include: val_to_array(args[:include]),
42
+ exclude: val_to_array(args[:exclude])
43
+ }
44
+ end
45
+
46
+ def val_to_array(val)
47
+ val.blank? ? val : val.split(/\W+/)
48
+ end
49
+ end
@@ -84,6 +84,38 @@ describe Hubspot::Contact do
84
84
  end
85
85
  end
86
86
 
87
+ describe '.create_or_update!' do
88
+ cassette 'create_or_update'
89
+ let(:existing_contact) do
90
+ Hubspot::Contact.create!("morpheus@example.com", firstname: 'Morpheus')
91
+ end
92
+ before do
93
+ Hubspot::Contact.create_or_update!(params)
94
+ end
95
+
96
+ let(:params) do
97
+ [
98
+ {
99
+ vid: existing_contact.vid,
100
+ email: existing_contact.email,
101
+ firstname: 'Neo'
102
+ },
103
+ {
104
+ email: 'smith@example.com',
105
+ firstname: 'Smith'
106
+ }
107
+ ]
108
+ end
109
+
110
+ it 'creates and updates contacts' do
111
+ contact = Hubspot::Contact.find_by_id existing_contact.vid
112
+ expect(contact.properties['firstname']).to eql 'Neo'
113
+ latest_contact_email = Hubspot::Contact.all(recent: true).first.email
114
+ new_contact = Hubspot::Contact.find_by_email(latest_contact_email)
115
+ expect(new_contact.properties['firstname']).to eql 'Smith'
116
+ end
117
+ end
118
+
87
119
  describe '.find_by_email' do
88
120
  context 'given an uniq email' do
89
121
  cassette 'contact_find_by_email'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubspot-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew DiMichele
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-20 00:00:00.000000000 Z
11
+ date: 2016-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -227,6 +227,7 @@ files:
227
227
  - lib/hubspot/railtie.rb
228
228
  - lib/hubspot/topic.rb
229
229
  - lib/hubspot/utils.rb
230
+ - lib/tasks/properties.rake
230
231
  - spec/lib/hubspot-ruby_spec.rb
231
232
  - spec/lib/hubspot/blog_spec.rb
232
233
  - spec/lib/hubspot/company_properties_spec.rb