hubspot-ruby 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -22
  3. data/Gemfile.lock +14 -11
  4. data/LICENSE.txt +0 -2
  5. data/README.md +8 -6
  6. data/RELEASING.md +4 -5
  7. data/Rakefile +2 -17
  8. data/hubspot-ruby.gemspec +20 -157
  9. data/lib/hubspot-ruby.rb +10 -0
  10. data/lib/hubspot/blog.rb +1 -2
  11. data/lib/hubspot/company.rb +149 -0
  12. data/lib/hubspot/company_properties.rb +59 -0
  13. data/lib/hubspot/config.rb +10 -4
  14. data/lib/hubspot/connection.rb +12 -4
  15. data/lib/hubspot/contact.rb +52 -31
  16. data/lib/hubspot/contact_list.rb +16 -16
  17. data/lib/hubspot/contact_properties.rb +53 -6
  18. data/lib/hubspot/deal.rb +2 -2
  19. data/lib/hubspot/deal_pipeline.rb +43 -0
  20. data/lib/hubspot/deal_properties.rb +59 -0
  21. data/lib/hubspot/engagement.rb +133 -0
  22. data/lib/hubspot/exceptions.rb +1 -1
  23. data/lib/hubspot/form.rb +20 -20
  24. data/lib/hubspot/owner.rb +49 -0
  25. data/lib/hubspot/properties.rb +119 -0
  26. data/lib/hubspot/railtie.rb +10 -0
  27. data/lib/hubspot/topic.rb +2 -2
  28. data/lib/hubspot/utils.rb +106 -3
  29. data/spec/lib/hubspot/blog_spec.rb +2 -0
  30. data/spec/lib/hubspot/company_properties_spec.rb +239 -0
  31. data/spec/lib/hubspot/company_spec.rb +190 -0
  32. data/spec/lib/hubspot/config_spec.rb +1 -1
  33. data/spec/lib/hubspot/connection_spec.rb +33 -27
  34. data/spec/lib/hubspot/contact_list_spec.rb +61 -61
  35. data/spec/lib/hubspot/contact_properties_spec.rb +234 -3
  36. data/spec/lib/hubspot/contact_spec.rb +140 -71
  37. data/spec/lib/hubspot/deal_properties_spec.rb +254 -0
  38. data/spec/lib/hubspot/engagement_spec.rb +87 -0
  39. data/spec/lib/hubspot/form_spec.rb +72 -60
  40. data/spec/lib/hubspot/owner_spec.rb +56 -0
  41. data/spec/lib/hubspot/properties_spec.rb +45 -0
  42. data/spec/lib/hubspot/topic_spec.rb +0 -1
  43. data/spec/lib/hubspot/utils_spec.rb +113 -15
  44. data/spec/lib/tasks/properties_spec.rb +90 -0
  45. data/spec/live/companies_integration_spec.rb +23 -0
  46. data/spec/live/companies_properties_integration_spec.rb +120 -0
  47. data/spec/live/contacts_integration_spec.rb +1 -1
  48. data/spec/live/contacts_properties_integration_spec.rb +120 -0
  49. data/spec/live/deal_properties_integration_spec.rb +123 -0
  50. data/spec/live/deals_integration_spec.rb +1 -1
  51. data/spec/support/cassette_helper.rb +1 -1
  52. data/spec/support/tests_helper.rb +3 -3
  53. metadata +39 -78
  54. data/.document +0 -5
  55. data/lib/hubspot/version.rb +0 -9
  56. data/spec/fixtures/vcr_cassettes/add_contacts_to_lists.yml +0 -281
  57. data/spec/fixtures/vcr_cassettes/blog_list.yml +0 -180
  58. data/spec/fixtures/vcr_cassettes/blog_posts.yml +0 -107
  59. data/spec/fixtures/vcr_cassettes/blog_posts_list.yml +0 -6463
  60. data/spec/fixtures/vcr_cassettes/contact_create.yml +0 -64
  61. data/spec/fixtures/vcr_cassettes/contact_create_existing_email.yml +0 -62
  62. data/spec/fixtures/vcr_cassettes/contact_create_invalid_email.yml +0 -63
  63. data/spec/fixtures/vcr_cassettes/contact_create_with_params.yml +0 -64
  64. data/spec/fixtures/vcr_cassettes/contact_destroy.yml +0 -131
  65. data/spec/fixtures/vcr_cassettes/contact_example.yml +0 -32
  66. data/spec/fixtures/vcr_cassettes/contact_find_by_email.yml +0 -59
  67. data/spec/fixtures/vcr_cassettes/contact_find_by_email_batch_mode.yml +0 -509
  68. data/spec/fixtures/vcr_cassettes/contact_find_by_id.yml +0 -59
  69. data/spec/fixtures/vcr_cassettes/contact_find_by_id_batch_mode.yml +0 -33
  70. data/spec/fixtures/vcr_cassettes/contact_find_by_utk.yml +0 -83
  71. data/spec/fixtures/vcr_cassettes/contact_find_by_utk_batch_mode.yml +0 -33
  72. data/spec/fixtures/vcr_cassettes/contact_list_batch_find.yml +0 -65
  73. data/spec/fixtures/vcr_cassettes/contact_list_destroy.yml +0 -63
  74. data/spec/fixtures/vcr_cassettes/contact_list_example.yml +0 -33
  75. data/spec/fixtures/vcr_cassettes/contact_list_find.yml +0 -96
  76. data/spec/fixtures/vcr_cassettes/contact_list_refresh.yml +0 -33
  77. data/spec/fixtures/vcr_cassettes/contact_list_update.yml +0 -36
  78. data/spec/fixtures/vcr_cassettes/contact_update.yml +0 -66
  79. data/spec/fixtures/vcr_cassettes/contacts_among_list.yml +0 -189
  80. data/spec/fixtures/vcr_cassettes/create_form.yml +0 -39
  81. data/spec/fixtures/vcr_cassettes/create_list.yml +0 -36
  82. data/spec/fixtures/vcr_cassettes/create_list_with_filters.yml +0 -36
  83. data/spec/fixtures/vcr_cassettes/deal_create.yml +0 -61
  84. data/spec/fixtures/vcr_cassettes/deal_example.yml +0 -166
  85. data/spec/fixtures/vcr_cassettes/deal_find.yml +0 -115
  86. data/spec/fixtures/vcr_cassettes/destroy_deal.yml +0 -221
  87. data/spec/fixtures/vcr_cassettes/fail_to_create_form.yml +0 -35
  88. data/spec/fixtures/vcr_cassettes/fail_to_create_list.yml +0 -35
  89. data/spec/fixtures/vcr_cassettes/field_among_form.yml +0 -34
  90. data/spec/fixtures/vcr_cassettes/fields_among_form.yml +0 -35
  91. data/spec/fixtures/vcr_cassettes/find_all_contacts.yml +0 -297
  92. data/spec/fixtures/vcr_cassettes/find_all_dynamic_lists.yml +0 -104
  93. data/spec/fixtures/vcr_cassettes/find_all_forms.yml +0 -15378
  94. data/spec/fixtures/vcr_cassettes/find_all_lists.yml +0 -138
  95. data/spec/fixtures/vcr_cassettes/find_all_recent_contacts.yml +0 -33
  96. data/spec/fixtures/vcr_cassettes/find_all_recent_updated_deals.yml +0 -130
  97. data/spec/fixtures/vcr_cassettes/find_all_stastic_lists.yml +0 -21876
  98. data/spec/fixtures/vcr_cassettes/form_destroy.yml +0 -64
  99. data/spec/fixtures/vcr_cassettes/form_example.yml +0 -39
  100. data/spec/fixtures/vcr_cassettes/form_find.yml +0 -69
  101. data/spec/fixtures/vcr_cassettes/form_post.yml +0 -31
  102. data/spec/fixtures/vcr_cassettes/form_submit_data.yml +0 -130
  103. data/spec/fixtures/vcr_cassettes/form_update.yml +0 -77
  104. data/spec/fixtures/vcr_cassettes/one_month_blog_posts_filter_state.yml +0 -19127
  105. data/spec/fixtures/vcr_cassettes/one_month_blog_posts_list.yml +0 -34963
  106. data/spec/fixtures/vcr_cassettes/remove_contacts_from_lists.yml +0 -315
  107. data/spec/fixtures/vcr_cassettes/topic_list.yml +0 -48
  108. data/spec/fixtures/vcr_cassettes/topics_list.yml +0 -86
@@ -0,0 +1,59 @@
1
+ module Hubspot
2
+ class CompanyProperties < Properties
3
+
4
+ ALL_PROPERTIES_PATH = '/companies/v2/properties'
5
+ ALL_GROUPS_PATH = '/companies/v2/groups'
6
+ CREATE_PROPERTY_PATH = '/companies/v2/properties/'
7
+ UPDATE_PROPERTY_PATH = '/companies/v2/properties/named/:property_name'
8
+ DELETE_PROPERTY_PATH = '/companies/v2/properties/named/:property_name'
9
+ CREATE_GROUP_PATH = '/companies/v2/groups/'
10
+ UPDATE_GROUP_PATH = '/companies/v2/groups/named/:group_name'
11
+ DELETE_GROUP_PATH = '/companies/v2/groups/named/:group_name'
12
+
13
+ class << self
14
+ def add_default_parameters(opts={})
15
+ superclass.add_default_parameters(opts)
16
+ end
17
+
18
+ def all(opts={}, filter={})
19
+ superclass.all(ALL_PROPERTIES_PATH, opts, filter)
20
+ end
21
+
22
+ def groups(opts={}, filter={})
23
+ superclass.groups(ALL_GROUPS_PATH, opts, filter)
24
+ end
25
+
26
+ def create!(params={})
27
+ superclass.create!(CREATE_PROPERTY_PATH, params)
28
+ end
29
+
30
+ def update!(property_name, params={})
31
+ superclass.update!(UPDATE_PROPERTY_PATH, property_name, params)
32
+ end
33
+
34
+ def delete!(property_name)
35
+ superclass.delete!(DELETE_PROPERTY_PATH, property_name)
36
+ end
37
+
38
+ def create_group!(params={})
39
+ superclass.create_group!(CREATE_GROUP_PATH, params)
40
+ end
41
+
42
+ def update_group!(group_name, params={})
43
+ superclass.update_group!(UPDATE_GROUP_PATH, group_name, params)
44
+ end
45
+
46
+ def delete_group!(group_name)
47
+ superclass.delete_group!(DELETE_GROUP_PATH, group_name)
48
+ end
49
+
50
+ def same?(src, dst)
51
+ superclass.same?(src, dst)
52
+ end
53
+
54
+ def valid_params(params)
55
+ superclass.valid_params(params)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,15 +1,20 @@
1
+ require 'logger'
2
+
1
3
  module Hubspot
2
4
  class Config
5
+
6
+ CONFIG_KEYS = [:hapikey, :base_url, :portal_id, :logger]
7
+ DEFAULT_LOGGER = Logger.new('/dev/null')
8
+
3
9
  class << self
4
- attr_reader :hapikey
5
- attr_reader :base_url
6
- attr_reader :portal_id
10
+ attr_accessor *CONFIG_KEYS
7
11
 
8
12
  def configure(config)
9
13
  config.stringify_keys!
10
14
  @hapikey = config["hapikey"]
11
15
  @base_url = config["base_url"] || "https://api.hubapi.com"
12
16
  @portal_id = config["portal_id"]
17
+ @logger = config['logger'] || DEFAULT_LOGGER
13
18
  self
14
19
  end
15
20
 
@@ -17,6 +22,7 @@ module Hubspot
17
22
  @hapikey = nil
18
23
  @base_url = "https://api.hubapi.com"
19
24
  @portal_id = nil
25
+ @logger = DEFAULT_LOGGER
20
26
  end
21
27
 
22
28
  def ensure!(*params)
@@ -28,4 +34,4 @@ module Hubspot
28
34
 
29
35
  reset!
30
36
  end
31
- end
37
+ end
@@ -6,6 +6,7 @@ module Hubspot
6
6
  def get_json(path, opts)
7
7
  url = generate_url(path, opts)
8
8
  response = get(url, format: :json)
9
+ log_request_and_response url, response
9
10
  raise(Hubspot::RequestError.new(response)) unless response.success?
10
11
  response.parsed_response
11
12
  end
@@ -15,6 +16,7 @@ module Hubspot
15
16
 
16
17
  url = generate_url(path, opts[:params])
17
18
  response = post(url, body: opts[:body].to_json, headers: { 'Content-Type' => 'application/json' }, format: :json)
19
+ log_request_and_response url, response, opts[:body]
18
20
  raise(Hubspot::RequestError.new(response)) unless response.success?
19
21
 
20
22
  no_parse ? response : response.parsed_response
@@ -23,6 +25,7 @@ module Hubspot
23
25
  def put_json(path, opts)
24
26
  url = generate_url(path, opts[:params])
25
27
  response = put(url, body: opts[:body].to_json, headers: { 'Content-Type' => 'application/json' }, format: :json)
28
+ log_request_and_response url, response, opts[:body]
26
29
  raise(Hubspot::RequestError.new(response)) unless response.success?
27
30
  response.parsed_response
28
31
  end
@@ -30,12 +33,17 @@ module Hubspot
30
33
  def delete_json(path, opts)
31
34
  url = generate_url(path, opts)
32
35
  response = delete(url, format: :json)
36
+ log_request_and_response url, response, opts[:body]
33
37
  raise(Hubspot::RequestError.new(response)) unless response.success?
34
38
  response
35
39
  end
36
40
 
37
41
  protected
38
42
 
43
+ def log_request_and_response(uri, response, body=nil)
44
+ Hubspot::Config.logger.info "Hubspot: #{uri}.\nBody: #{body}.\nResponse: #{response.code} #{response.body}"
45
+ end
46
+
39
47
  def generate_url(path, params={}, options={})
40
48
  Hubspot::Config.ensure! :hapikey
41
49
  path = path.clone
@@ -85,11 +93,11 @@ module Hubspot
85
93
  end
86
94
 
87
95
  class FormsConnection < Connection
88
- follow_redirects false
96
+ follow_redirects true
89
97
 
90
98
  def self.submit(path, opts)
91
- url = generate_url(path, opts[:params], { base_url: 'https://forms.hubspot.com' })
92
- post(url, body: opts[:body].to_json, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' })
99
+ url = generate_url(path, opts[:params], { base_url: 'https://forms.hubspot.com', hapikey: false })
100
+ post(url, body: opts[:body], headers: { 'Content-Type' => 'application/x-www-form-urlencoded' })
93
101
  end
94
102
  end
95
- end
103
+ end
@@ -6,22 +6,24 @@ 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"
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
13
  CONTACT_BATCH_PATH = '/contacts/v1/contact/vids/batch'
14
- GET_CONTACT_BY_UTK_PATH = "/contacts/v1/contact/utk/:contact_utk/profile"
14
+ GET_CONTACT_BY_UTK_PATH = '/contacts/v1/contact/utk/:contact_utk/profile'
15
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"
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
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'
20
22
 
21
23
  class << self
22
24
  # {https://developers.hubspot.com/docs/methods/contacts/create_contact}
23
25
  def create!(email, params={})
24
- params_with_email = params.stringify_keys.merge("email" => email)
26
+ params_with_email = params.stringify_keys.merge('email' => email)
25
27
  post_data = {properties: Hubspot::Utils.hash_to_properties(params_with_email)}
26
28
  response = Hubspot::Connection.post_json(CREATE_CONTACT_PATH, params: {}, body: post_data )
27
29
  new(response)
@@ -30,11 +32,11 @@ module Hubspot
30
32
  # {https://developers.hubspot.com/docs/methods/contacts/get_contacts}
31
33
  # {https://developers.hubspot.com/docs/methods/contacts/get_recently_updated_contacts}
32
34
  def all(opts={})
33
- recent = opts.delete(:recent) { false }
34
- path, opts =
35
- if recent
36
- [RECENT_CONTACTS_PATH, Hubspot::ContactProperties.add_default_parameters(opts)]
37
- else
35
+ recent = opts.delete(:recent) { false }
36
+ path, opts =
37
+ if recent
38
+ [RECENT_CONTACTS_PATH, Hubspot::ContactProperties.add_default_parameters(opts)]
39
+ else
38
40
  [CONTACTS_PATH, opts]
39
41
  end
40
42
 
@@ -46,6 +48,13 @@ module Hubspot
46
48
  # PATH /contacts/v1/contact/createOrUpdate/email/:contact_email
47
49
  # API endpoint: https://developers.hubspot.com/docs/methods/contacts/create_or_update
48
50
  # + batch mode: https://developers.hubspot.com/docs/methods/contacts/batch_create_or_update
51
+ def createOrUpdate(email, params={})
52
+ post_data = {properties: Hubspot::Utils.hash_to_properties(params.stringify_keys)}
53
+ response = Hubspot::Connection.post_json(CREATE_OR_UPDATE_PATH, params: { contact_email: email }, body: post_data )
54
+ contact = find_by_id(response['vid'])
55
+ contact.is_new = response['isNew']
56
+ contact
57
+ end
49
58
 
50
59
  # NOTE: problem with batch api endpoint
51
60
  # {https://developers.hubspot.com/docs/methods/contacts/get_contact}
@@ -71,18 +80,22 @@ module Hubspot
71
80
  else raise Hubspot::InvalidParams, 'expecting String or Array of Strings parameter'
72
81
  end
73
82
 
74
- response = Hubspot::Connection.get_json(path, params)
75
- if batch_mode
76
- #TODO: transform response
77
- response
78
- else
79
- new(response)
83
+ begin
84
+ response = Hubspot::Connection.get_json(path, params)
85
+ if batch_mode
86
+ response.map{|_, contact| new(contact)}
87
+ else
88
+ new(response)
89
+ end
90
+ rescue => e
91
+ raise e unless e.message =~ /not exist/ # 404 / handle the error and kindly return nil
92
+ nil
80
93
  end
81
94
  end
82
95
 
83
96
  # NOTE: problem with batch api endpoint
84
97
  # {https://developers.hubspot.com/docs/methods/contacts/get_contact_by_utk}
85
- # {https://developers.hubspot.com/docs/methods/contacts/get_batch_by_utk}
98
+ # {https://developers.hubspot.com/docs/methods/contacts/get_batch_by_utk}
86
99
  def find_by_utk(utks)
87
100
  batch_mode, path, params = case utks
88
101
  when String then [false, GET_CONTACT_BY_UTK_PATH, { contact_utk: utks }]
@@ -96,17 +109,21 @@ module Hubspot
96
109
  end
97
110
 
98
111
  # {https://developers.hubspot.com/docs/methods/contacts/search_contacts}
99
- def search(query, count=100)
100
- raise NotImplementedError
112
+ def search(query, options = {})
113
+ count = options.fetch(:count, 100)
114
+ offset = options.fetch(:offset, 0)
115
+
116
+ response = Hubspot::Connection.get_json(QUERY_PATH, { q: query, count: count, offset: offset })
117
+ response.merge("contacts" => response["contacts"].map { |contact_hash| new(contact_hash) })
101
118
  end
102
119
  end
103
120
 
104
- attr_reader :properties
105
- attr_reader :vid
121
+ attr_reader :properties, :vid, :is_new
106
122
 
107
123
  def initialize(response_hash)
108
- @properties = Hubspot::Utils.properties_to_hash(response_hash["properties"])
109
- @vid = response_hash["vid"]
124
+ props = response_hash['properties']
125
+ @properties = Hubspot::Utils.properties_to_hash(props) unless props.blank?
126
+ @vid = response_hash['vid']
110
127
  end
111
128
 
112
129
  def [](property)
@@ -114,11 +131,15 @@ module Hubspot
114
131
  end
115
132
 
116
133
  def email
117
- @properties["email"]
134
+ @properties['email']
118
135
  end
119
136
 
120
137
  def utk
121
- @properties["usertoken"]
138
+ @properties['usertoken']
139
+ end
140
+
141
+ def is_new=(val)
142
+ @is_new = val
122
143
  end
123
144
 
124
145
  # Updates the properties of a contact
@@ -127,7 +148,7 @@ module Hubspot
127
148
  # @return [Hubspot::Contact] self
128
149
  def update!(params)
129
150
  query = {"properties" => Hubspot::Utils.hash_to_properties(params.stringify_keys!)}
130
- response = Hubspot::Connection.post_json(UPDATE_CONTACT_PATH, params: { contact_id: vid }, body: query)
151
+ Hubspot::Connection.post_json(UPDATE_CONTACT_PATH, params: { contact_id: vid }, body: query)
131
152
  @properties.merge!(params)
132
153
  self
133
154
  end
@@ -136,7 +157,7 @@ module Hubspot
136
157
  # {https://developers.hubspot.com/docs/methods/contacts/delete_contact}
137
158
  # @return [TrueClass] true
138
159
  def destroy!
139
- response = Hubspot::Connection.delete_json(DESTROY_CONTACT_PATH, { contact_id: vid })
160
+ Hubspot::Connection.delete_json(DESTROY_CONTACT_PATH, { contact_id: vid })
140
161
  @destroyed = true
141
162
  end
142
163
 
@@ -15,10 +15,10 @@ module Hubspot
15
15
  class << self
16
16
  # {http://developers.hubspot.com/docs/methods/lists/create_list}
17
17
  def create!(opts={})
18
- dynamic = opts.delete(:dynamic) { false }
19
- portal_id = opts.delete(:portal_id) { Hubspot::Config.portal_id }
20
-
21
- response = Hubspot::Connection.post_json(LISTS_PATH, params: {}, body: opts.merge({ dynamic: dynamic, portal_id: portal_id}) )
18
+ dynamic = opts.delete(:dynamic) { false }
19
+ portal_id = opts.delete(:portal_id) { Hubspot::Config.portal_id }
20
+
21
+ response = Hubspot::Connection.post_json(LISTS_PATH, params: {}, body: opts.merge({ dynamic: dynamic, portal_id: portal_id}) )
22
22
  new(response)
23
23
  end
24
24
 
@@ -26,11 +26,11 @@ module Hubspot
26
26
  # {http://developers.hubspot.com/docs/methods/lists/get_static_lists}
27
27
  # {http://developers.hubspot.com/docs/methods/lists/get_dynamic_lists}
28
28
  def all(opts={})
29
- static = opts.delete(:static) { false }
30
- dynamic = opts.delete(:dynamic) { false }
29
+ static = opts.delete(:static) { false }
30
+ dynamic = opts.delete(:dynamic) { false }
31
31
 
32
32
  # NOTE: As opposed of what the documentation says, getting the static or dynamic lists returns all the lists, not only 20 lists
33
- path = LISTS_PATH + (static ? '/static' : dynamic ? '/dynamic' : '')
33
+ path = LISTS_PATH + (static ? '/static' : dynamic ? '/dynamic' : '')
34
34
  response = Hubspot::Connection.get_json(path, opts)
35
35
  response['lists'].map { |l| new(l) }
36
36
  end
@@ -38,12 +38,12 @@ module Hubspot
38
38
  # {http://developers.hubspot.com/docs/methods/lists/get_list}
39
39
  # {http://developers.hubspot.com/docs/methods/lists/get_batch_lists}
40
40
  def find(ids)
41
- batch_mode, path, params = case ids
41
+ batch_mode, path, params = case ids
42
42
  when Integer then [false, LIST_PATH, { list_id: ids }]
43
- when String then [false, LIST_PATH, { list_id: ids.to_i }]
43
+ when String then [false, LIST_PATH, { list_id: ids.to_i }]
44
44
  when Array then [true, LIST_BATCH_PATH, { batch_list_id: ids.map(&:to_i) }]
45
45
  else raise Hubspot::InvalidParams, 'expecting Integer or Array of Integers parameter'
46
- end
46
+ end
47
47
 
48
48
  response = Hubspot::Connection.get_json(path, params)
49
49
  batch_mode ? response['lists'].map { |l| new(l) } : new(response)
@@ -77,17 +77,17 @@ module Hubspot
77
77
  def contacts(opts={})
78
78
  # NOTE: caching functionality can be dependant of the nature of the list, if dynamic or not ...
79
79
  bypass_cache = opts.delete(:bypass_cache) { false }
80
- recent = opts.delete(:recent) { false }
80
+ recent = opts.delete(:recent) { false }
81
81
 
82
82
  if bypass_cache || @contacts.nil?
83
83
  path = recent ? RECENT_CONTACTS_PATH : CONTACTS_PATH
84
84
  opts[:list_id] = @id
85
-
85
+
86
86
  response = Hubspot::Connection.get_json(path, Hubspot::ContactProperties.add_default_parameters(opts))
87
87
  @contacts = response['contacts'].map { |c| Hubspot::Contact.new(c) }
88
88
  else
89
89
  @contacts
90
- end
90
+ end
91
91
  end
92
92
 
93
93
  # {http://developers.hubspot.com/docs/methods/lists/refresh_list}
@@ -97,12 +97,12 @@ module Hubspot
97
97
  end
98
98
 
99
99
  # {http://developers.hubspot.com/docs/methods/lists/add_contact_to_list}
100
- def add(contacts)
100
+ def add(contacts)
101
101
  contact_ids = [contacts].flatten.uniq.compact.map(&:vid)
102
102
  response = Hubspot::Connection.post_json(ADD_CONTACT_PATH, params: { list_id: @id }, body: { vids: contact_ids })
103
103
  response['updated'].sort == contact_ids.sort
104
104
  end
105
-
105
+
106
106
  # {http://developers.hubspot.com/docs/methods/lists/remove_contact_from_list}
107
107
  def remove(contacts)
108
108
  contact_ids = [contacts].flatten.uniq.compact.map(&:vid)
@@ -124,4 +124,4 @@ module Hubspot
124
124
  @properties = hash
125
125
  end
126
126
  end
127
- end
127
+ end
@@ -1,11 +1,58 @@
1
1
  module Hubspot
2
- class ContactProperties
3
- class << self
4
- # TODO: properties can be set as configuration
5
- # TODO: find the way how to set a list of Properties + merge same property key if present from opts
2
+ class ContactProperties < Properties
3
+
4
+ ALL_PROPERTIES_PATH = '/contacts/v2/properties'
5
+ ALL_GROUPS_PATH = '/contacts/v2/groups'
6
+ CREATE_PROPERTY_PATH = '/contacts/v2/properties/'
7
+ UPDATE_PROPERTY_PATH = '/contacts/v2/properties/named/:property_name'
8
+ DELETE_PROPERTY_PATH = '/contacts/v2/properties/named/:property_name'
9
+ CREATE_GROUP_PATH = '/contacts/v2/groups/'
10
+ UPDATE_GROUP_PATH = '/contacts/v2/groups/named/:group_name'
11
+ DELETE_GROUP_PATH = '/contacts/v2/groups/named/:group_name'
12
+
13
+ class << self
6
14
  def add_default_parameters(opts={})
7
- properties = 'email'
8
- opts.merge(property: properties)
15
+ superclass.add_default_parameters(opts)
16
+ end
17
+
18
+ def all(opts={}, filter={})
19
+ superclass.all(ALL_PROPERTIES_PATH, opts, filter)
20
+ end
21
+
22
+ def groups(opts={}, filter={})
23
+ superclass.groups(ALL_GROUPS_PATH, opts, filter)
24
+ end
25
+
26
+ def create!(params={})
27
+ superclass.create!(CREATE_PROPERTY_PATH, params)
28
+ end
29
+
30
+ def update!(property_name, params={})
31
+ superclass.update!(UPDATE_PROPERTY_PATH, property_name, params)
32
+ end
33
+
34
+ def delete!(property_name)
35
+ superclass.delete!(DELETE_PROPERTY_PATH, property_name)
36
+ end
37
+
38
+ def create_group!(params={})
39
+ superclass.create_group!(CREATE_GROUP_PATH, params)
40
+ end
41
+
42
+ def update_group!(group_name, params={})
43
+ superclass.update_group!(UPDATE_GROUP_PATH, group_name, params)
44
+ end
45
+
46
+ def delete_group!(group_name)
47
+ superclass.delete_group!(DELETE_GROUP_PATH, group_name)
48
+ end
49
+
50
+ def same?(src, dst)
51
+ superclass.same?(src, dst)
52
+ end
53
+
54
+ def valid_params(params)
55
+ superclass.valid_params(params)
9
56
  end
10
57
  end
11
58
  end