ruby_hubspot_api 0.2 → 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
  SHA256:
3
- metadata.gz: 67b58c873d1e9277df15b213a804afe47189c888aab565963950bf9992050e07
4
- data.tar.gz: 62028c4b6b0a2ac9a9a29e88cf4762cbbdb909942415d1bc2bf02e3838b405eb
3
+ metadata.gz: f455ed36bd0ae0284959198213bea7924099b97fc0b43b4ac50b4ad21a73def2
4
+ data.tar.gz: 9ba207fcf4fdf8c14889d130a0cdd3284ff75816873d994084d80b410e8306e1
5
5
  SHA512:
6
- metadata.gz: 98ec373c58ef3aa92eb963d2ab567bd41204bd1c80552e0abacf4cadc1a6860d5b227dde78f5fbfe8b6d3cdff65536390116f468492c6f639e87c1a83f4e60ff
7
- data.tar.gz: 5bea871875782b5fd35ff62de85c11da16f7e763a88972ac3d6cbca3e6b700eca589eed7933058434d9c6574079b71fd5e2d0aabc8fcc3be288dd27d5a9ae405
6
+ metadata.gz: 0d4274f0519d4fe99a09f06405689a3b45145a6890b4c5a1052e7e6e38bf91ae4ce9d96669d8bb97a5acd7e92110a0eeac4c73e7e0e6ea3b93fd1393f2f4c648
7
+ data.tar.gz: 42829d5342d0dbd126b9200b609c662518dce48e55a82a6e3f6536ee4ed7bdf1c9af14007114e1f883ca036df53cc49522d239d803e5bdfceb525170a18adbac
@@ -0,0 +1,47 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "main" ]
13
+ pull_request:
14
+ branches: [ "main" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.5', '2.6', '2.7', '3.0']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: ${{ matrix.ruby-version }}
34
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
35
+
36
+ - name: Run tests
37
+ run: HUBSPOT_LOG_LEVEL=FATAL bundle exec rspec
38
+
39
+ - name: Upload coverage to Codecov
40
+ run: bash <(curl -s https://codecov.io/bash)
41
+ env:
42
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
43
+
44
+ - name: Upload coverage to Codacy
45
+ run: bash <(curl -Ls https://coverage.codacy.com/get.sh)
46
+ env:
47
+ CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  # rspec failure tracking
7
7
  .rspec_status
8
8
  .pry_history
9
+ .ruby-version
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_hubspot_api (0.1.2.1)
4
+ ruby_hubspot_api (0.2)
5
5
  httparty (>= 0.1, < 1.0)
6
6
 
7
7
  GEM
@@ -11,6 +11,9 @@ GEM
11
11
  public_suffix (>= 2.0.2, < 7.0)
12
12
  bigdecimal (3.1.8)
13
13
  byebug (11.1.3)
14
+ codecov (0.2.12)
15
+ json
16
+ simplecov
14
17
  coderay (1.1.3)
15
18
  crack (1.0.0)
16
19
  bigdecimal
@@ -22,6 +25,7 @@ GEM
22
25
  httparty (0.21.0)
23
26
  mini_mime (>= 1.0.0)
24
27
  multi_xml (>= 0.5.2)
28
+ json (2.7.2)
25
29
  method_source (1.1.0)
26
30
  mini_mime (1.1.2)
27
31
  multi_xml (0.6.0)
@@ -52,6 +56,7 @@ GEM
52
56
  simplecov-html (~> 0.11)
53
57
  simplecov_json_formatter (~> 0.1)
54
58
  simplecov-html (0.13.1)
59
+ simplecov-lcov (0.8.0)
55
60
  simplecov_json_formatter (0.1.4)
56
61
  vcr (6.0.0)
57
62
  webmock (3.23.1)
@@ -60,19 +65,23 @@ GEM
60
65
  hashdiff (>= 0.4.0, < 2.0.0)
61
66
 
62
67
  PLATFORMS
68
+ ruby
63
69
  x86_64-darwin-18
70
+ x86_64-linux
64
71
 
65
72
  DEPENDENCIES
66
- bundler (>= 2.0)
73
+ bundler (>= 2.0, < 2.4.0)
74
+ codecov
67
75
  dotenv (>= 2.0)
68
76
  pry (>= 0.1)
69
77
  pry-byebug (>= 3.0)
70
78
  rake (>= 11.0, < 14.0)
71
79
  rspec (>= 3.0)
72
80
  ruby_hubspot_api!
73
- simplecov (>= 0.22, < 1.0)
81
+ simplecov
82
+ simplecov-lcov
74
83
  vcr (>= 6.0)
75
84
  webmock (>= 3.0)
76
85
 
77
86
  BUNDLED WITH
78
- 2.3.26
87
+ 2.3.27
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Ruby HubSpot API Gem
2
2
 
3
+ [![codecov](https://codecov.io/gh/sensadrome/ruby_hubspot_api/branch/main/graph/badge.svg)](https://codecov.io/gh/sensadrome/ruby_hubspot_api) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/504ca01245ee4928b6ed0b13801259e7)](https://app.codacy.com/gh/sensadrome/ruby_hubspot_api/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
4
+
3
5
  This gem was largely inspired by [hubspot-api-ruby](https://github.com/captaincontrat/hubspot-api-ruby) which, in turn, was inspired by the [hubspot-ruby](https://github.com/HubspotCommunity/hubspot-ruby) community gem. I wanted to use version 3 of the api and simplify some parts of the interface
4
6
 
5
7
  The Ruby HubSpot API gem is a starting point for building an ORM-like interface to HubSpot's API.
@@ -30,19 +32,54 @@ To authenticate API requests, you need a HubSpot access token. First you will ne
30
32
 
31
33
  You can configure the gem by adding this code to your initializer (for Rails) or to your startup configuration (in any other environment):
32
34
 
35
+ ##### Minimum configuration
36
+
33
37
  ```ruby
34
38
  Hubspot.configure do |config|
35
39
  config.access_token = 'your_access_token'
36
40
  end
37
41
  ```
38
42
 
43
+ ##### Full possible configuration
44
+
45
+ ```ruby
46
+ Hubspot.configure do |config|
47
+ config.access_token = 'your_access_token'
48
+ config.portal_id = 'your_portal_id'
49
+ config.client_secret = 'your_client_secret'
50
+ config.logger = Rails.logger
51
+ config.log_level = 'info' # debug,info,warn,error,fatal
52
+ config.timeout = 10 # seconds to timeout all api requests
53
+ config.open_timeout = 5 # open_timeout seconds
54
+ config.read_timeout = 5 # read_timeout seconds
55
+ config.write_timeout = 5 # swrite_timeout econds (ruby >= 2.6)
56
+ end
57
+ ```
58
+
39
59
  This configuration ensures that your API requests are authenticated using your HubSpot access token.
40
60
 
41
- ## Working with Objects
61
+ ## Working with Resources
62
+
63
+ This gem allows you to interact with Hubspot resources such as contacts and companies. You can perform operations on individual resources (e.g., creating or updating records) as well as on collections (e.g., listing or searching).
64
+
65
+ __please note__
66
+
67
+ > In the Hubspot API contacts, companies etc are referred to as "Objects" (e.g. CRM > Objects > Contacts) so when we use the word "Object" (with a capital O) we will be referring to an object in Hubspot
42
68
 
43
- _(N.B when referring to the resources in the api we will refer to them as Objects as per the Hubspot nomenclature)_
69
+ > In this gem we use the term Resource so as not to accidentally overload Object! When we use the term "Resource" we should be referring to the ruby ORM base class and when we say "resource" we should be referring to an instance of this class (or a class that inherits it)
44
70
 
45
- This gem allows you to interact with HubSpot objects such as contacts and companies. You can perform operations on individual instances (e.g., creating or updating records) as well as on collections (e.g., listing or searching).
71
+ ### Hubspot::Resource class
72
+
73
+ This is the base ORM class for all Hubspot CRM objects. You should not operate on this class but with the following classes each of which inherits from Hubspot::Resource
74
+
75
+ ```ruby
76
+ Hubspot::Contact # crm > contacts
77
+ Hubspot::Company # crm > companies
78
+ Hubspot::User # hubspot users (also referred to as 'owners')
79
+ Hubspot::Owner # alias of Hubspot::User if you prefer to use it
80
+ ```
81
+
82
+ however you can [add custom objects of your own](#user-content-custom-resources) based on your own custom defined Objects in Hubspot
46
83
 
47
84
  ### Creating and Saving an Object
48
85
 
@@ -178,12 +215,12 @@ This will automatically set the limits and handle paging for the most efficient
178
215
 
179
216
  By default Hubspot will only send back the [default hubspot properties](https://knowledge.hubspot.com/properties/hubspots-default-contact-properties)
180
217
 
181
- You can pass an array of properties to be return as follows:
218
+ You can pass an array of properties to be returned as follows:
182
219
 
183
220
  Example:
184
221
 
185
222
  ```ruby
186
- # Search for contacts with email containing "hubspot.com" and only return specific properties
223
+ # Get the full list of contacts and only return specific properties
187
224
  contacts = Hubspot::Contact.list(
188
225
  properties: ['firstname', 'lastname', 'email', 'mobile', 'custom_property_1']
189
226
  )
@@ -327,7 +364,9 @@ batch.each_page do |contacts|
327
364
  end
328
365
  ```
329
366
 
330
- Finally there is another helper method on re
367
+ Finally there is another helper method `batch_read_all` on any Hubspot::Resource class (Hubspot::Contact, Hubspot::Company, Hubspot::User etc) which will read all of the resources and return a HubSpot::Batch (with all of the resources).
368
+
369
+ You can then update the resources and call `update` on the batch.... see below
331
370
 
332
371
  #### Batch Update
333
372
 
@@ -348,13 +387,12 @@ batch.update
348
387
 
349
388
  Example using a batch
350
389
  ```ruby
351
- contact_ids = my_contacts.collect(&:hubspot_id).compact
352
- batch = Hubspot::contacts.batch_read(contact_ids)
390
+ user_ids = my_selected_users.collect(&:hubspot_id).compact
391
+ batch = Hubspot::User.batch_read(user_ids)
353
392
 
354
- batch.resources.each do |hubspot_contact|
355
- my_contact = my_contacts.find { |c| c.hubspot_id == hubspot_contact.id }
356
- # some logic or method to set any new/changed properties on hubspot_contact
357
- update_hubspot_contact_from_local(hubspot_contact, my_contact)
393
+ batch.resources.each do |hubspot_user|
394
+ # some logic or method to set any new/changed properties on hubspot_user
395
+ hubspot_user.sales_total = fetch_sales_total(user.email)
358
396
  end
359
397
 
360
398
  # now we have a batch with changed resources we can update the batch
@@ -404,6 +442,31 @@ else
404
442
  end
405
443
  ```
406
444
 
445
+ ## Custom Resources
446
+
447
+ If you have defined custom objects you can easily add them by creating a class that inherits from `Hubspot::Resource`
448
+
449
+ ```ruby
450
+ # lib/hubspot/projects.rb
451
+
452
+ require 'ruby_hubspot_api' # if not required by bundler already...
453
+
454
+ module Hubspot
455
+ class Project < Resource
456
+
457
+ # resource_name (part of the url in the api) will default
458
+ # to a simple plural of the class name - in this case 'projects'
459
+ # if the url for your custom object is different you can override it
460
+
461
+ def resource_name
462
+ 'company_projects'
463
+ end
464
+ end
465
+ end
466
+
467
+ projects = Hubspot::Projects.search(query: { status_in: ['upcoming', 'active', 'overrun'] }).all
468
+
469
+ ```
407
470
 
408
471
  ## Contributing
409
472
 
@@ -11,5 +11,9 @@ module Hubspot
11
11
  "#<#{self.class} #{formatted_attrs}>"
12
12
  end
13
13
  # :nocov:
14
+
15
+ def read_only?
16
+ modificationMetadata['readOnlyValue'] == true
17
+ end
14
18
  end
15
19
  end
@@ -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,10 +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
191
+ def updatable_properties
192
+ properties.reject(&:read_only?)
193
+ end
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
198
+ def read_only_properties
199
+ properties.select(&:read_only)
200
+ end
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
85
209
  def property(property_name)
86
210
  properties.detect { |prop| prop.name == property_name }
87
211
  end
@@ -98,6 +222,45 @@ module Hubspot
98
222
  }.freeze
99
223
 
100
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.
101
264
  def search(query:, properties: [], page_size: 100)
102
265
  search_body = {}
103
266
 
@@ -177,6 +340,23 @@ module Hubspot
177
340
  end
178
341
 
179
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)
180
360
  def initialize(data = {})
181
361
  data.transform_keys!(&:to_s)
182
362
  @id = extract_id(data)
@@ -188,13 +368,23 @@ module Hubspot
188
368
  initialize_new_object(data)
189
369
  end
190
370
  end
371
+
191
372
  # rubocop:enable Ling/MissingSuper
192
373
 
374
+ # Determine the state of the object
375
+ #
376
+ # Returns Boolean
193
377
  def changes?
194
378
  !@changes.empty?
195
379
  end
196
380
 
197
- # 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
198
388
  def save
199
389
  if persisted?
200
390
  self.class.update(@id, @changes).tap do |result|
@@ -208,11 +398,22 @@ module Hubspot
208
398
  end
209
399
  end
210
400
 
401
+ # If the resource exists in Hubspot
402
+ #
403
+ # Returns Boolean
211
404
  def persisted?
212
405
  @id ? true : false
213
406
  end
214
407
 
215
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
216
417
  def update(params)
217
418
  raise 'Not able to update as not persisted' unless persisted?
218
419
 
@@ -223,6 +424,12 @@ module Hubspot
223
424
  save
224
425
  end
225
426
 
427
+ # Archive the object in Hubspot
428
+ #
429
+ # Example:
430
+ # company = Hubspot::Company.find(hubspot_company_id)
431
+ # company.delete
432
+ #
226
433
  def delete
227
434
  self.class.archive(id)
228
435
  end
@@ -233,7 +440,11 @@ module Hubspot
233
440
  end
234
441
 
235
442
  # rubocop:disable Metrics/MethodLength
236
- # 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)
237
448
  def method_missing(method, *args)
238
449
  method_name = method.to_s
239
450
 
@@ -259,9 +470,10 @@ module Hubspot
259
470
  # Fallback if the method or attribute is not found
260
471
  super
261
472
  end
473
+
262
474
  # rubocop:enable Metrics/MethodLength
263
475
 
264
- # Ensure respond_to_missing? is properly overridden
476
+ # Ensure respond_to_missing? handles existing keys in the properties anc changes hashes
265
477
  def respond_to_missing?(method_name, include_private = false)
266
478
  property_name = method_name.to_s.chomp('=')
267
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'
4
+ VERSION = '0.2.1'
5
5
  end
@@ -40,12 +40,14 @@ Gem::Specification.new do |spec|
40
40
  # Define development dependencies
41
41
  spec.add_development_dependency 'rake', '>= 11.0', '< 14.0'
42
42
 
43
- spec.add_development_dependency 'bundler', '>= 2.0'
43
+ spec.add_development_dependency 'bundler', '>= 2.0', '< 2.4.0'
44
+ spec.add_development_dependency 'codecov'
44
45
  spec.add_development_dependency 'dotenv', '>= 2.0'
45
46
  spec.add_development_dependency 'pry', '>= 0.1'
46
47
  spec.add_development_dependency 'pry-byebug', '>= 3.0'
47
48
  spec.add_development_dependency 'rspec', '>= 3.0'
48
- spec.add_development_dependency 'simplecov', '>= 0.22', '< 1.0'
49
+ spec.add_development_dependency 'simplecov'
50
+ spec.add_development_dependency 'simplecov-lcov'
49
51
  spec.add_development_dependency 'vcr', '>= 6.0'
50
52
  spec.add_development_dependency 'webmock', '>= 3.0'
51
53
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_hubspot_api
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Brook
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-29 00:00:00.000000000 Z
11
+ date: 2024-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -37,6 +37,9 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '2.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: 2.4.0
40
43
  type: :development
41
44
  prerelease: false
42
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,6 +47,23 @@ dependencies:
44
47
  - - ">="
45
48
  - !ruby/object:Gem::Version
46
49
  version: '2.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: 2.4.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: codecov
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
47
67
  - !ruby/object:Gem::Dependency
48
68
  name: dotenv
49
69
  requirement: !ruby/object:Gem::Requirement
@@ -106,20 +126,28 @@ dependencies:
106
126
  requirements:
107
127
  - - ">="
108
128
  - !ruby/object:Gem::Version
109
- version: '0.22'
110
- - - "<"
111
- - !ruby/object:Gem::Version
112
- version: '1.0'
129
+ version: '0'
113
130
  type: :development
114
131
  prerelease: false
115
132
  version_requirements: !ruby/object:Gem::Requirement
116
133
  requirements:
117
134
  - - ">="
118
135
  - !ruby/object:Gem::Version
119
- version: '0.22'
120
- - - "<"
136
+ version: '0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: simplecov-lcov
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
121
142
  - !ruby/object:Gem::Version
122
- version: '1.0'
143
+ version: '0'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
123
151
  - !ruby/object:Gem::Dependency
124
152
  name: vcr
125
153
  requirement: !ruby/object:Gem::Requirement
@@ -176,10 +204,10 @@ extensions: []
176
204
  extra_rdoc_files: []
177
205
  files:
178
206
  - ".env.sample"
207
+ - ".github/workflows/ruby.yml"
179
208
  - ".gitignore"
180
209
  - ".rspec"
181
210
  - ".rubocop.yml"
182
- - ".ruby-version"
183
211
  - CHANGELOG.md
184
212
  - Gemfile
185
213
  - Gemfile.lock
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.5.3