ruby_hubspot_api 0.2.1.pre.1 → 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
- SHA1:
3
- metadata.gz: 2ca83fa3cba8c574d585b31a359da74678d405d2
4
- data.tar.gz: 151f119e552b17faff4d921cda1ceec62a3fc045
2
+ SHA256:
3
+ metadata.gz: f455ed36bd0ae0284959198213bea7924099b97fc0b43b4ac50b4ad21a73def2
4
+ data.tar.gz: 9ba207fcf4fdf8c14889d130a0cdd3284ff75816873d994084d80b410e8306e1
5
5
  SHA512:
6
- metadata.gz: e2e95c0a9ef1b69ff862c7843bbb100b23d57fe29cfea0d2042a7593dc3760307d48027fc0b54a6ae05bd39c4721db7603e04a7b16a5ec51b50a1becc436fdc1
7
- data.tar.gz: 9dd953ca1946b3f9c3f1d0616f377a330f7e894f6a0f1a1aa6e98fde137015b6c39148dec58437c5cf027d89b9e096dbeb36b144a368ed8f1e61aa2a673305d7
6
+ metadata.gz: 0d4274f0519d4fe99a09f06405689a3b45145a6890b4c5a1052e7e6e38bf91ae4ce9d96669d8bb97a5acd7e92110a0eeac4c73e7e0e6ea3b93fd1393f2f4c648
7
+ data.tar.gz: 42829d5342d0dbd126b9200b609c662518dce48e55a82a6e3f6536ee4ed7bdf1c9af14007114e1f883ca036df53cc49522d239d803e5bdfceb525170a18adbac
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_hubspot_api (0.2.1)
4
+ ruby_hubspot_api (0.2)
5
5
  httparty (>= 0.1, < 1.0)
6
6
 
7
7
  GEM
@@ -9,33 +9,35 @@ GEM
9
9
  specs:
10
10
  addressable (2.8.7)
11
11
  public_suffix (>= 2.0.2, < 7.0)
12
- bigdecimal (3.0.2)
12
+ bigdecimal (3.1.8)
13
13
  byebug (11.1.3)
14
- codecov (0.6.0)
15
- simplecov (>= 0.15, < 0.22)
14
+ codecov (0.2.12)
15
+ json
16
+ simplecov
16
17
  coderay (1.1.3)
17
18
  crack (1.0.0)
18
19
  bigdecimal
19
20
  rexml
20
21
  diff-lcs (1.5.1)
21
- docile (1.3.5)
22
+ docile (1.4.1)
22
23
  dotenv (2.8.1)
23
24
  hashdiff (1.1.1)
24
25
  httparty (0.21.0)
25
26
  mini_mime (>= 1.0.0)
26
27
  multi_xml (>= 0.5.2)
28
+ json (2.7.2)
27
29
  method_source (1.1.0)
28
30
  mini_mime (1.1.2)
29
31
  multi_xml (0.6.0)
30
- pry (0.14.2)
32
+ pry (0.13.1)
31
33
  coderay (~> 1.1)
32
34
  method_source (~> 1.0)
33
- pry-byebug (3.8.0)
35
+ pry-byebug (3.9.0)
34
36
  byebug (~> 11.0)
35
- pry (~> 0.10)
37
+ pry (~> 0.13.0)
36
38
  public_suffix (4.0.7)
37
39
  rake (13.2.1)
38
- rexml (3.2.5)
40
+ rexml (3.3.7)
39
41
  rspec (3.13.0)
40
42
  rspec-core (~> 3.13.0)
41
43
  rspec-expectations (~> 3.13.0)
@@ -49,13 +51,15 @@ GEM
49
51
  diff-lcs (>= 1.2.0, < 2.0)
50
52
  rspec-support (~> 3.13.0)
51
53
  rspec-support (3.13.1)
52
- simplecov (0.18.5)
54
+ simplecov (0.22.0)
53
55
  docile (~> 1.1)
54
56
  simplecov-html (~> 0.11)
57
+ simplecov_json_formatter (~> 0.1)
55
58
  simplecov-html (0.13.1)
56
59
  simplecov-lcov (0.8.0)
60
+ simplecov_json_formatter (0.1.4)
57
61
  vcr (6.0.0)
58
- webmock (3.18.1)
62
+ webmock (3.23.1)
59
63
  addressable (>= 2.8.0)
60
64
  crack (>= 0.3.2)
61
65
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -80,4 +84,4 @@ DEPENDENCIES
80
84
  webmock (>= 3.0)
81
85
 
82
86
  BUNDLED WITH
83
- 2.2.34
87
+ 2.3.27
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # HubSpot API Client
4
- # Handles all HTTP interactions with the HubSpot API. It manages GET, POST, PATCH, and DELETE requests.
5
3
  module Hubspot
6
4
  # All interations with the Hubspot API happen here...
7
5
  class ApiClient
@@ -15,11 +15,6 @@ module Hubspot
15
15
  apply_log_level
16
16
  end
17
17
 
18
- # Apply the log level to the logger
19
- def apply_log_level
20
- @logger.level = @log_level
21
- end
22
-
23
18
  private
24
19
 
25
20
  # Initialize the default logger
@@ -48,6 +43,11 @@ module Hubspot
48
43
  end
49
44
  # rubocop:enable Metrics/MethodLength
50
45
 
46
+ # Apply the log level to the logger
47
+ def apply_log_level
48
+ @logger.level = @log_level
49
+ end
50
+
51
51
  # Set the default log level based on environment
52
52
  def default_log_level
53
53
  if defined?(Rails) && Rails.env.test?
@@ -6,20 +6,65 @@ require_relative './paged_batch'
6
6
 
7
7
  module Hubspot
8
8
  # rubocop:disable Metrics/ClassLength
9
- # Hubspot::Resource class
9
+
10
+ # HubSpot Resource Base Class
11
+ # This class provides common functionality for interacting with HubSpot API resources such as Contacts, Companies, etc
12
+ #
13
+ # It supports common operations like finding, creating, updating, and deleting resources, as well as batch operations.
14
+ #
15
+ # This class is meant to be inherited by specific resources like `Hubspot::Contact`.
16
+ #
17
+ # You can access the properties of a resource instance by calling the property name as method
18
+ #
19
+ # Example Usage:
20
+ # Hubspot::Contact.find(1)
21
+ # contact.name # 'Luke'
22
+ #
23
+ # company = Hubspot::Company.create(name: "Acme Corp")
24
+ # company.id.nil? # false
25
+ #
10
26
  class Resource < ApiClient
11
27
  METADATA_FIELDS = %w[createdate hs_object_id lastmodifieddate].freeze
12
28
 
13
- # Allow read/write access to properties and metadata
14
- attr_accessor :id, :properties, :changes, :metadata
29
+ # Allow read/write access to id, properties, changes and metadata
30
+
31
+ # the id of the object in hubspot
32
+ attr_accessor :id
33
+
34
+ # the properties as if read from the api
35
+ attr_accessor :properties
36
+
37
+ # track any changes made to properties before saving etc
38
+ attr_accessor :changes
39
+
40
+ # any other data sent from the api about the resource
41
+ attr_accessor :metadata
15
42
 
16
43
  class << self
17
44
  # Find a resource by ID and return an instance of the class
45
+ #
46
+ # id - [Integer] The ID (or hs_object_id) of the resource to fetch.
47
+ #
48
+ # Example:
49
+ # contact = Hubspot::Contact.find(1)
50
+ #
51
+ # Returns An instance of the resource.
18
52
  def find(id)
19
53
  response = get("/crm/v3/objects/#{resource_name}/#{id}")
20
54
  instantiate_from_response(response)
21
55
  end
22
56
 
57
+ # Finds a resource by a given property and value.
58
+ #
59
+ # property - The property to search by (e.g., "email").
60
+ # value - The value of the property to match.
61
+ # properties - Optional list of properties to return.
62
+ #
63
+ # Example:
64
+ # properties = %w[firstname lastname email last_contacted]
65
+ # contact = Hubspot::Contact.find_by("email", "john@example.com", properties)
66
+ #
67
+ # Returns An instance of the resource.
23
68
  def find_by(property, value, properties = nil)
24
69
  params = { idProperty: property }
25
70
  params[:properties] = properties if properties.is_a?(Array)
@@ -27,12 +72,28 @@ module Hubspot
27
72
  instantiate_from_response(response)
28
73
  end
29
74
 
30
- # Create a new resource
75
+ # Creates a new resource with the given parameters.
76
+ #
77
+ # params - The properties to create the resource with.
78
+ #
79
+ # Example:
80
+ # contact = Hubspot::Contact.create(name: "John Doe", email: "john@example.com")
81
+ #
82
+ # Returns [Resource] The newly created resource.
31
83
  def create(params)
32
84
  response = post("/crm/v3/objects/#{resource_name}", body: { properties: params }.to_json)
33
85
  instantiate_from_response(response)
34
86
  end
35
87
 
88
+ # Updates an existing resource by ID.
89
+ #
90
+ # id - The ID of the resource to update.
91
+ # params - The properties to update.
92
+ #
93
+ # Example:
94
+ # contact.update(1, name: "Jane Doe")
95
+ #
96
+ # Returns True if the update was successful, false if not
36
97
  def update(id, params)
37
98
  response = patch("/crm/v3/objects/#{resource_name}/#{id}", body: { properties: params }.to_json)
38
99
  raise Hubspot.error_from_response(response) unless response.success?
@@ -40,6 +101,14 @@ module Hubspot
40
101
  true
41
102
  end
42
103
 
104
+ # Deletes a resource by ID.
105
+ #
106
+ # id - The ID of the resource to delete.
107
+ #
108
+ # Example:
109
+ # Hubspot::Contact.archive(1)
110
+ #
111
+ # Returns True if the deletion was successful, false if not
43
112
  def archive(id)
44
113
  response = delete("/crm/v3/objects/#{resource_name}/#{id}")
45
114
  raise Hubspot.error_from_response(response) unless response.success?
@@ -47,6 +116,14 @@ module Hubspot
47
116
  true
48
117
  end
49
118
 
119
+ # Lists all resources with optional filters and pagination.
120
+ #
121
+ # params - Optional parameters to filter or paginate the results.
122
+ #
123
+ # Example:
124
+ # contacts = Hubspot::Contact.list(limit: 100)
125
+ #
126
+ # Returns [PagedCollection] A collection of resources.
50
127
  def list(params = {})
51
128
  PagedCollection.new(
52
129
  url: "/crm/v3/objects/#{resource_name}",
@@ -55,6 +132,17 @@ module Hubspot
55
132
  )
56
133
  end
57
134
 
135
+ # Performs a batch read operation to retrieve multiple resources by their IDs.
136
+ #
137
+ # object_ids - A list of resource IDs to fetch.
138
+ #
139
+ # id_property - The property to use for identifying resources (default: 'id').
140
+ #
141
+ #
142
+ # Example:
143
+ # Hubspot::Contact.batch_read([1, 2, 3])
144
+ #
145
+ # Returns [PagedBatch] A paged batch of resources (call .each_page to cycle through pages from the API)
58
146
  def batch_read(object_ids = [], id_property: 'id')
59
147
  params = id_property == 'id' ? {} : { idProperty: id_property }
60
148
 
@@ -66,11 +154,23 @@ module Hubspot
66
154
  )
67
155
  end
68
156
 
157
+ # Performs a batch read operation to retrieve multiple resources by their IDs
158
+ # until there are none left
159
+ #
160
+ # object_ids - A list of resource IDs to fetch. [Array<Integer>]
161
+ # id_property - The property to use for identifying resources (default: 'id').
162
+ #
163
+ # Example:
164
+ # Hubspot::Contact.batch_read([1, 2, 3])
165
+ #
166
+ # Returns [Hubspot::Batch] A batch of resources that can be operated on further
69
167
  def batch_read_all(object_ids = [], id_property: 'id')
70
168
  Hubspot::Batch.read(self, object_ids, id_property: id_property)
71
169
  end
72
170
 
73
- # Get the complete list of fields (properties) for the object
171
+ # Retrieve the complete list of properties for this resource class
172
+ #
173
+ # Returns [Array<Hubspot::Property>] An array of hubspot properties
74
174
  def properties
75
175
  @properties ||= begin
76
176
  response = get("/crm/v3/properties/#{resource_name}")
@@ -78,18 +178,34 @@ module Hubspot
78
178
  end
79
179
  end
80
180
 
181
+ # Retrieve the complete list of user defined properties for this resource class
182
+ #
183
+ # Returns [Array<Hubspot::Property>] An array of hubspot properties
81
184
  def custom_properties
82
185
  properties.reject { |property| property['hubspotDefined'] }
83
186
  end
84
187
 
188
+ # Retrieve the complete list of updatable properties for this resource class
189
+ #
190
+ # Returns [Array<Hubspot::Property>] An array of updateable hubspot properties
85
191
  def updatable_properties
86
192
  properties.reject(&:read_only?)
87
193
  end
88
194
 
195
+ # Retrieve the complete list of read-only properties for this resource class
196
+ #
197
+ # Returns [Array<Hubspot::Property>] An array of read-only hubspot properties
89
198
  def read_only_properties
90
- properties.select(&:read_only?)
199
+ properties.select(&:read_only)
91
200
  end
92
201
 
202
+ # Retrieve information about a specific property
203
+ #
204
+ # Example:
205
+ # property = Hubspot::Contact.property('industry_sector')
206
+ # values_for_select = property.options.each_with_object({}) { |prop, ps| ps[prop['value']] = prop['label'] }
207
+ #
208
+ # Returns [Array<Hubspot::Property>] An array of hubspot properties
93
209
  def property(property_name)
94
210
  properties.detect { |prop| prop.name == property_name }
95
211
  end
@@ -106,6 +222,45 @@ module Hubspot
106
222
  }.freeze
107
223
 
108
224
  # rubocop:disable Metrics/MethodLength
225
+
226
+ # Search for resources using a flexible query format and optional properties.
227
+ #
228
+ # This method allows searching for resources by passing a query in the form of a string (for full-text search)
229
+ # or a hash with special suffixes on the keys to define different comparison operators.
230
+ # You can also specify which properties to return and the number of results per page.
231
+ #
232
+ # Available suffixes for query keys (when using a hash):
233
+ # - `_contains`: Matches values that contain the given string.
234
+ # - `_gt`: Greater than comparison.
235
+ # - `_lt`: Less than comparison.
236
+ # - `_gte`: Greater than or equal to comparison.
237
+ # - `_lte`: Less than or equal to comparison.
238
+ # - `_neq`: Not equal to comparison.
239
+ # - `_in`: Matches any of the values in the given array.
240
+ #
241
+ # If no suffix is provided, the default comparison is equality (`EQ`).
242
+ #
243
+ # query - [String, Hash] The query for searching. This can be either:
244
+ # - A String: for full-text search.
245
+ # - A Hash: where each key represents a property and may have suffixes for the comparison
246
+ # (e.g., `{ email_contains: 'example.org', age_gt: 30 }`).
247
+ # properties - An optional array of property names to return in the search results. [Array<String>]
248
+ # If not specified or empty, HubSpot will return the default set of properties.
249
+ # page_size - The number of results to return per page (default is 10 for contacts and 100 for everything else).
250
+ #
251
+ # Example Usage:
252
+ # # Full-text search for 'example.org':
253
+ # contacts = Hubspot::Contact.search(query: "example.org",
254
+ # properties: ["email", "firstname", "lastname"], page_size: 50)
255
+ #
256
+ # # Search for contacts whose email contains 'example.org' and are older than 30:
257
+ # contacts = Hubspot::Contact.search(
258
+ # query: { email_contains: 'example.org', age_gt: 30 },
259
+ # properties: ["email", "firstname", "lastname"],
260
+ # page_size: 50
261
+ # )
262
+ #
263
+ # Returns [PagedCollection] A paged collection of results that can be iterated over.
109
264
  def search(query:, properties: [], page_size: 100)
110
265
  search_body = {}
111
266
 
@@ -185,6 +340,23 @@ module Hubspot
185
340
  end
186
341
 
187
342
  # rubocop:disable Ling/MissingSuper
343
+
344
+ # Public: Initialize a resouce
345
+ #
346
+ # data - [2D Hash, nested Hash] data to initialise the resourse This can be either:
347
+ # - A Simple 2D Hash, key value pairs of property => value (for the create option)
348
+ # - A structured hash consisting of { id: <hs_object_id>, properties: {}, ... }
349
+ # This is the same structure as per the API, and can be rebuilt if you store the id
350
+ # of the object against your own data
351
+ #
352
+ # Example:
353
+ # contact = Hubspot::Contact.new(firstname: 'Luke', lastname: 'Skywalker', email: 'luke@jedi.org')
354
+ # contact.persisted? # false
355
+ # contact.save # creates the record in Hubspot
356
+ # contact.persisted? # true
357
+ # puts "Contact saved with hubspot id #{contact.id}"
358
+ #
359
+ # existing_contact = Hubspot::Contact.new(id: hubspot_id, properties: contact.to_hubspot_properties)
188
360
  def initialize(data = {})
189
361
  data.transform_keys!(&:to_s)
190
362
  @id = extract_id(data)
@@ -196,13 +368,23 @@ module Hubspot
196
368
  initialize_new_object(data)
197
369
  end
198
370
  end
371
+
199
372
  # rubocop:enable Ling/MissingSuper
200
373
 
374
+ # Determine the state of the object
375
+ #
376
+ # Returns Boolean
201
377
  def changes?
202
378
  !@changes.empty?
203
379
  end
204
380
 
205
- # Instance methods for update (or save)
381
+ # Create or Update the resource.
382
+ # If the resource was already persisted (e.g. it was retrieved from the API)
383
+ # it will be updated using values from @changes
384
+ #
385
+ # If the resource is new (no id) it will be created
386
+ #
387
+ # Returns Boolean
206
388
  def save
207
389
  if persisted?
208
390
  self.class.update(@id, @changes).tap do |result|
@@ -216,11 +398,22 @@ module Hubspot
216
398
  end
217
399
  end
218
400
 
401
+ # If the resource exists in Hubspot
402
+ #
403
+ # Returns Boolean
219
404
  def persisted?
220
405
  @id ? true : false
221
406
  end
222
407
 
223
408
  # Update the resource
409
+ #
410
+ # params - hash of properties to update in key value pairs
411
+ #
412
+ # Example:
413
+ # contact = Hubspot::Contact.find(hubspot_contact_id)
414
+ # contact.update(status: 'gold customer', last_contacted_at: Time.now.utc.iso8601)
415
+ #
416
+ # Returns Boolean
224
417
  def update(params)
225
418
  raise 'Not able to update as not persisted' unless persisted?
226
419
 
@@ -231,6 +424,12 @@ module Hubspot
231
424
  save
232
425
  end
233
426
 
427
+ # Archive the object in Hubspot
428
+ #
429
+ # Example:
430
+ # company = Hubspot::Company.find(hubspot_company_id)
431
+ # company.delete
432
+ #
234
433
  def delete
235
434
  self.class.archive(id)
236
435
  end
@@ -241,7 +440,11 @@ module Hubspot
241
440
  end
242
441
 
243
442
  # rubocop:disable Metrics/MethodLength
244
- # Handle dynamic getter and setter methods with method_missing
443
+
444
+ # getter: Check the properties and changes hashes to see if the method
445
+ # being called is a key, and return the corresponding value
446
+ # setter: If the method ends in "=" persist the value in the changes hash
447
+ # (when it is different from the corresponding value in properties if set)
245
448
  def method_missing(method, *args)
246
449
  method_name = method.to_s
247
450
 
@@ -267,9 +470,10 @@ module Hubspot
267
470
  # Fallback if the method or attribute is not found
268
471
  super
269
472
  end
473
+
270
474
  # rubocop:enable Metrics/MethodLength
271
475
 
272
- # Ensure respond_to_missing? is properly overridden
476
+ # Ensure respond_to_missing? handles existing keys in the properties anc changes hashes
273
477
  def respond_to_missing?(method_name, include_private = false)
274
478
  property_name = method_name.to_s.chomp('=')
275
479
  @properties.key?(property_name) || @changes.key?(property_name) || super
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hubspot
4
- VERSION = '0.2.1-1'
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/hubspot.rb CHANGED
@@ -20,7 +20,6 @@ module Hubspot
20
20
  yield(config) if block_given?
21
21
  set_client_headers if config.access_token
22
22
  set_request_timeouts
23
- config.apply_log_level
24
23
  end
25
24
 
26
25
  def configured?
@@ -9,30 +9,3 @@ class Object
9
9
  end
10
10
  end
11
11
  end
12
-
13
- # At some point this will seem like a bad idea ;)
14
-
15
- # :nocov:
16
- if RUBY_VERSION < '2.5.0'
17
- class Hash
18
- # Non-mutating version (returns a new hash with transformed keys)
19
- def transform_keys
20
- return enum_for(:transform_keys) unless block_given?
21
- result = {}
22
- each_key do |key|
23
- result[yield(key)] = self[key]
24
- end
25
- result
26
- end
27
-
28
- # Mutating version (modifies the hash in place)
29
- def transform_keys!
30
- return enum_for(:transform_keys!) unless block_given?
31
- keys.each do |key|
32
- self[yield(key)] = delete(key)
33
- end
34
- self
35
- end
36
- end
37
- end
38
- # :nocov:end
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.homepage = 'https://github.com/sensadrome/ruby_hubspot_api'
17
17
  spec.license = 'MIT'
18
18
 
19
- spec.required_ruby_version = '>= 2.4'
19
+ spec.required_ruby_version = '>= 2.5'
20
20
 
21
21
  # Prevent pushing this gem to RubyGems.org.
22
22
  # To allow pushes either set the 'allowed_push_host'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_hubspot_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1.pre.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Brook
@@ -246,15 +246,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
246
246
  requirements:
247
247
  - - ">="
248
248
  - !ruby/object:Gem::Version
249
- version: '2.4'
249
+ version: '2.5'
250
250
  required_rubygems_version: !ruby/object:Gem::Requirement
251
251
  requirements:
252
- - - ">"
252
+ - - ">="
253
253
  - !ruby/object:Gem::Version
254
- version: 1.3.1
254
+ version: '0'
255
255
  requirements: []
256
- rubyforge_project:
257
- rubygems_version: 2.6.14.4
256
+ rubygems_version: 3.2.3
258
257
  signing_key:
259
258
  specification_version: 4
260
259
  summary: ruby_hubspot_api is an ORM-like wrapper for the Hubspot API