hubspot-ruby 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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