procore 0.8.8 → 1.1.3

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
- SHA256:
3
- metadata.gz: cc64539748539d38af7f3dedc9a825ae8dff0f84939a53cddf1bf124dcba6c0a
4
- data.tar.gz: 3a5bbe135e42bbf3d05e7d68a45829bf6dc185334e73ea579ca88cee66ccb757
2
+ SHA1:
3
+ metadata.gz: dd1eb304ce63c6fc2163b5dc0fbb5e98f02e2172
4
+ data.tar.gz: 7f616999b991a439f252ecee53a73c2e63d3fda0
5
5
  SHA512:
6
- metadata.gz: f3450511913a6f4c6933a263dfc05d4b564f49978bc334ae043100f4b028b3191dbc486ef0f42bc623da510e3922789a6abbc8120d8f7539e1164c06f91452c5
7
- data.tar.gz: 2f82f682587398a82831a024a86fff4c986edc4927828a4fb478ef58a6d3b45f080a3dc9822aaf4c7a1a1ac212d7bf53b829efeaa5286d246d86be305a8fe92e
6
+ metadata.gz: 3b812a82954028fb21d708b42ecfe509ff735a11c29bb01eecf3d1952e5a5b6d3b246b8187d887254bbd9b6c2057dc96890580a92952e9e9c4f30e75a813ca2e
7
+ data.tar.gz: 81a4a77d7b1af2a17dc5cea4400376372d84fbf533b20ae6c02f12f12a197d06c14172bc8659fa1b6d9b7592bbb247a484d2361d9646b5afcd33dda0e34c5b75
data/.rubocop.yml CHANGED
@@ -1,5 +1,9 @@
1
+ require:
2
+ - rubocop-rails
3
+ - rubocop-performance
4
+
1
5
  AllCops:
2
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.5
3
7
  Include:
4
8
  - '**/Rakefile'
5
9
  - '**/config.ru'
@@ -305,7 +309,7 @@ Style/PerlBackrefs:
305
309
  Naming/PredicateName:
306
310
  Description: 'Check the names of predicate methods.'
307
311
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark'
308
- NamePrefixBlacklist:
312
+ ForbiddenPrefixes:
309
313
  - is_
310
314
  Exclude:
311
315
  - spec/**/*
@@ -437,7 +441,7 @@ Style/RedundantBegin:
437
441
 
438
442
  # Layout
439
443
 
440
- Layout/AlignParameters:
444
+ Layout/ParameterAlignment:
441
445
  Description: 'Here we check if the parameters on a multi-line method call or definition are aligned.'
442
446
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent'
443
447
  Enabled: false
@@ -505,7 +509,7 @@ Lint/DeprecatedClassMethods:
505
509
  Description: 'Check for deprecated class method calls.'
506
510
  Enabled: false
507
511
 
508
- Lint/DuplicatedKey:
512
+ Lint/DuplicateHashKey:
509
513
  Description: 'Check for duplicate keys in hash literals.'
510
514
  Enabled: false
511
515
 
@@ -521,7 +525,7 @@ Lint/FormatParameterMismatch:
521
525
  Description: 'The number of parameters to format/sprint must match the fields.'
522
526
  Enabled: false
523
527
 
524
- Lint/HandleExceptions:
528
+ Lint/SuppressedException:
525
529
  Description: "Don't suppress exception."
526
530
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions'
527
531
  Enabled: false
data/.travis.yml CHANGED
@@ -1,30 +1,25 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3
4
- - 2.4
5
- - 2.5
6
- - 2.6
7
-
3
+ - 2.3
4
+ - 2.4
5
+ - 2.5
6
+ - 2.6
8
7
  services:
9
- - redis-server
10
- - memcached
11
-
8
+ - redis-server
9
+ - memcached
12
10
  before_install:
13
- - gem update --system
14
- - gem install bundler
15
-
11
+ - gem update --system
12
+ - gem install bundler
16
13
  cache: bundler
17
-
18
14
  script: bundle exec rake
19
-
20
15
  deploy:
21
16
  provider: rubygems
22
17
  api_key:
23
- secure: GYH7nTi2D9ZwbCP+JYSgHceDUvZT9RQSP6yXFndwSyxdiSmB6wfq6EtoH4Wpznd6ALT6IxrtbR4aftTI9DO6HPq+PVO6NdxjkdlbdxxAqRQJBAwFwFATT8jCuuDjGPLf8PF0ouzcMvAIdIgHypwmLdevWdEMomWdRWlm1UFP/0C3RDjY1v04XDrRb+fEagPNnzMDCcO352nyFm06jnCq/ezjCRXBvNtHTZeqd7t9pbNw7gtYebZ3b9hfd4IIa68budeh+URygiPnNNWr6TCjO95IuHIeMDele3tir0KzqVBNsVAqEb7WpB26rf1JgneAoYZwVMFh+hk09cs68EbIELD4MX6/PzEUz2Ws20dIMjs1pcDtlw35ixoEpwC/vz2qVJyMRYXg8af5rpsZkKXRl7QP2LrX+xSEt4LiRnylj4PaRZWu1gvhC7fsCHXEM3mW3WlXFUmb9W4Jv8VooqOJtGhpD9Qs9pYtTOgJoEmYqttbuCaiYKaiPutBY4+t+t2ZmyCopv41nkjv/UCWXfo11ew1qK0rxDJVE2/JYTUDZ+zuHypTf2lHCWjyP65vGwBnmdixLnEMCUOkzKUmqFR4kAE6jRMEhtki4fTlFSIHJGM5oIXeRXDR43NIh7xWNvhl7lHkwWoRA0BfSITtvO8k0SefGnFwhNfOglQ/GKfyAaY=
24
- gem: procore
18
+ secure: LC+5qDeaqBtA8IIDt0yHNYsTA/KEs7IK/hESF2V2f4bhmMapifEVSjikoZVE1lTe0R2+CyO+5mWHloFeTLayTchpZhW3yfduei3l2tktZOH9UCsXIQZKveSZlCMQ+XOn65Gstbd/5krh9+axKZswgM5YgBhjXNRgjL+yOGh2kXN0exk5nBvIBFxSCQdwqGiBDcrtgJ4eWrlPgofXszMFb3ogNQcIuUcKmAOC0j/fNag4qQV0jnp3zHDuOjrsARPJn4w6RMqSLpFVUYpJw3tE94GDW5kILHr7taTPj12PeYNbYjW7kRSgMYbQlIWUKLeyMp+vw3kNqd3Ysat+M+Mrf3z2KRKR5w62IJnCq758uerCdUo5v/vsWHYFcJvZWLrvsPSk+xQWysAqRdkun7ZBCK/FLR75S6Vkm0DBnbqd/yYp6MP9Vbi77gIZpWMXANfdk1aWGVlPNpskYeWyqPjwZX1nYybJQIIpZfX21F2WPrNA9r/cj1KYjb8vKopMEdn9GP9xMeUXXu85K+ZVPqSD/AblrLHyD2x7cES/i4+XcQSaKUOSLxTUqemAiDRBahDCehPOOeLHnu/rUzgQr1gzQL0YcLNgHovmIdstljBys62JC4gy376cNawiSW4ZPMHWg6PewqQ6Ozg4Lkytx06bBwOos55dFgI4k0T4H0/6QiE=
19
+ gem: ruby-sdk
25
20
  on:
26
21
  tags: true
27
22
  repo: procore/ruby-sdk
28
-
23
+ skip_cleanup: 'true'
29
24
  notifications:
30
25
  email: false
data/CHANGELOG.md CHANGED
@@ -1,4 +1,90 @@
1
- ## Unreleased
1
+ ## 1.1.3 (Jun 11, 2021)
2
+
3
+ * Add Procore-Sdk-Language header to all requests
4
+
5
+ PR #45 - https://github.com/procore/ruby-sdk/pull/45
6
+
7
+ *Benjamin Ross*
8
+
9
+ * Remove Redis.exists warning
10
+
11
+ PR #46 - https://github.com/procore/ruby-sdk/pull/46
12
+
13
+ *claudioprocore*
14
+
15
+ ## 1.1.2 (Jun 4, 2021)
16
+
17
+ * Add Procore-Sdk-Version header to all requests
18
+
19
+ PR #44 - https://github.com/procore/ruby-sdk/pull/44
20
+
21
+ *Benjamin Ross*
22
+
23
+ ## 1.1.1 (May 5, 2021)
24
+
25
+ * Change default host to 'api.procore.com'.
26
+
27
+ PR #42 - https://github.com/procore/ruby-sdk/pull/42
28
+
29
+ *Nate Baer*
30
+
31
+ ## 1.1.0 (March 11, 2021)
32
+
33
+ * Allow tokens to be revoked and manually refreshed.
34
+
35
+ PR #39 - https://github.com/procore/ruby-sdk/pull/39
36
+
37
+ *Nate Baer*
38
+
39
+ ## 1.0.0 (January 5, 2021)
40
+
41
+ * Adds support for API versioning
42
+
43
+ *Nate Baer*
44
+
45
+ ### Upgrading
46
+
47
+ As of v1.0.0, this gem now defaults to making requests against Procore's new
48
+ Rest v1.0 resources, instead of the now deprecated `/vapid` namespace. Example:
49
+
50
+ ```ruby
51
+ # Previously makes a request to
52
+ client.get("me")
53
+ => app.procore.com/vapid/me
54
+
55
+ # In 1.0.0
56
+ client.get("me")
57
+ => app.procore.com/rest/v1.0/me
58
+ ```
59
+
60
+ To keep the legacy behavior, set the new `default_version` configuration option.
61
+ Note, that Rest v1.0 is a superset of the Vapid Api - there are no breaking
62
+ changes. The Vapid API will be decommissioned in December 2021.
63
+
64
+ [Read more here](https://developers.procore.com/documentation/vapid-deprecation)
65
+
66
+ ```ruby
67
+ Procore.configure do |config|
68
+ ...
69
+ # Defaults to "v1.0"
70
+ config.default_version = "vapid"
71
+ ...
72
+ end
73
+ ```
74
+
75
+ All the request methods (`get`, `post`, `patch`, `put`, `delete`, `sync`) now
76
+ accept an optional version parameter to specify the version at request time.
77
+
78
+ ```ruby
79
+ client.get("me")
80
+ => https://app.procore.com/rest/v1.0/me
81
+
82
+ client.get("me", version: "v1.1")
83
+ => https://app.procore.com/rest/v1.1/me
84
+
85
+ client.get("me", version: "vapid")
86
+ => https://app.procore.com/vapid/me
87
+ ```
2
88
 
3
89
  ## 0.8.8 (October 17, 2019)
4
90
 
data/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #### Table of Contents
6
6
  - [Installation](#installation)
7
+ - [1.0.0 Release](#100-release)
7
8
  - [Making Requests](#making-requests)
8
9
  - [Usage](#usage)
9
10
  - [Error Handling](#error-handling)
@@ -30,6 +31,11 @@ Add this line to your application's Gemfile:
30
31
  gem "procore"
31
32
  ```
32
33
 
34
+ ## 1.0.0 Release
35
+
36
+ v1.0.0 was released on January 5, 2021, and adds support the new Rest v1.0 API.
37
+ See the CHANGELOG for upgrade instructions.
38
+
33
39
  ## Making Requests
34
40
 
35
41
  At the core of the gem is the `Client` class. Clients are initialized with a
@@ -41,20 +47,30 @@ Stores automatically manage tokens for you - refreshing, revoking and storage
41
47
  are abstracted away to make your code as simple as possible. There are several
42
48
  different [types of stores](#stores) available to you.
43
49
 
44
- The Client class exposes `#get`, `#post`, `#put`, `#patch`, '#sync' and
50
+ The Client class exposes `#get`, `#post`, `#put`, `#patch`, `#sync` and
45
51
  `#delete` methods to you.
46
52
 
47
53
  ```ruby
48
- get(path, query: {})
49
- post(path, body: {}, options: {})
50
- put(path, body: {}, options: {})
51
- patch(path, body: {}, options: {})
52
- delete(path, query: {})
53
- sync(path, body: {}, options: {})
54
+ get(path, version: "", query: {})
55
+ post(path, version: "", body: {}, options: {})
56
+ put(path, version: "", body: {}, options: {})
57
+ patch(path, version: "", body: {}, options: {})
58
+ delete(path, version: "", query: {})
59
+ sync(path, version: "", body: {}, options: {})
54
60
  ```
55
61
 
56
- All paths are relative - the gem will handle expanding `client.get("me")` to
57
- `https://app.procore.com/vapid/me`.
62
+ All paths are relative, the gem will handle expanding them. An API version may
63
+ be specified in the `version:` argument, or the default version is used. The
64
+ default version is `v1.0` unless otherwise configured.
65
+
66
+ | Example | Requested URL |
67
+ | --- | --- |
68
+ | `client.get("me")` | `https://api.procore.com/rest/v1.0/me` |
69
+ | `client.get("me", version: "v1.1")` | `https://api.procore.com/rest/v1.1/me` |
70
+ | `client.get("me", version: "vapid")` | `https://api.procore.com/vapid/me` |
71
+
72
+ In addition to the settings above, you will need to set `company_id` in the request
73
+ options to work with [Multiple Procore Zones (MPZ)](https://developers.procore.com/documentation/tutorial-mpz).
58
74
 
59
75
  Example Usage:
60
76
 
@@ -70,6 +86,24 @@ client = Procore::Client.new(
70
86
  companies = client.get("companies")
71
87
 
72
88
  companies.first[:name] #=> "Procore Company 1"
89
+
90
+ # Get a company's projects (note the company_id value in options)
91
+ projects = client.get("projects", query: {company_id: <company_id>}, options: {company_id: <company_id>})
92
+
93
+ projects.first[:name] #=> "Project 1"
94
+ ```
95
+
96
+ To use Procore's older API Vapid by default, the default version can be set in
97
+ either the Gem's [configuration](https://github.com/procore/ruby-sdk#configuration)
98
+ or the client's `options` hash:
99
+
100
+ ```ruby
101
+ client = Procore::Client.new(
102
+ ...
103
+ options {
104
+ default_version: "vapid"
105
+ }
106
+ )
73
107
  ```
74
108
 
75
109
  ## Usage
@@ -115,6 +149,18 @@ client = Procore::Client.new(
115
149
  client.get("me")
116
150
  ```
117
151
 
152
+ Expired tokens will automatically be refreshed, but can also be refreshed manually:
153
+
154
+ ```ruby
155
+ client.refresh
156
+ ```
157
+
158
+ Tokens may also be manually revoked, forcing the client to refresh its token on the next request:
159
+
160
+ ```ruby
161
+ client.revoke
162
+ ```
163
+
118
164
  ## Error Handling
119
165
 
120
166
  The Procore Gem raises errors whenever a request returns a non `2xx` response.
@@ -317,13 +363,17 @@ Procore.configure do |config|
317
363
  # Base API host name. Alter this depending on your environment - in a
318
364
  # staging or test environment you may want to point this at a sandbox
319
365
  # instead of production.
320
- config.host = ENV.fetch("PROCORE_BASE_API_PATH", "https://app.procore.com")
366
+ config.host = ENV.fetch("PROCORE_BASE_API_PATH", "https://api.procore.com")
321
367
 
322
368
  # When using #sync action, sets the default batch size to use for chunking
323
369
  # up a request body. Example: if the size is set to 500, and 2,000 updates
324
370
  # are desired, 4 requests will be made. Note, the maximum size is 1000.
325
371
  config.default_batch_size = 500
326
372
 
373
+ # The default API version to use if none is specified in the request.
374
+ # Should be either "v1.0" (recommended) or "vapid" (legacy).
375
+ config.default_version = "v1.0"
376
+
327
377
  # Integer: Number of times to retry a failed API call. Reasons an API call
328
378
  # could potentially fail:
329
379
  # 1. Service is briefly down or unreachable
@@ -32,6 +32,17 @@ module Procore
32
32
  end
33
33
  end
34
34
 
35
+ def revoke(token:)
36
+ request = {
37
+ client_id: @client_id,
38
+ client_secret: @client_secret,
39
+ token: token.access_token,
40
+ }
41
+ client.request(:post, "/oauth/revoke", body: request)
42
+ rescue RestClient::ExceptionWithResponse
43
+ raise OAuthError.new(e.description, response: e.response)
44
+ end
45
+
35
46
  private
36
47
 
37
48
  def client
@@ -13,7 +13,7 @@ module Procore
13
13
  end
14
14
 
15
15
  def fetch
16
- return unless redis.exists(redis_key)
16
+ return unless redis.exists?(redis_key)
17
17
 
18
18
  token = JSON.parse(redis.get(redis_key))
19
19
  Procore::Auth::Token.new(
@@ -38,23 +38,56 @@ module Procore
38
38
  @store = store
39
39
  end
40
40
 
41
- private
41
+ # @raise [OAuthError] if a token cannot be refreshed.
42
+ def refresh
43
+ token = fetch_token
42
44
 
43
- def base_api_path
44
- "#{options[:host]}/#{api_version}"
45
+ begin
46
+ new_token = @credentials.refresh(
47
+ token: token.access_token,
48
+ refresh: token.refresh_token,
49
+ )
50
+
51
+ Util.log_info("Token Refresh Successful", store: store)
52
+ store.save(new_token)
53
+ rescue RuntimeError
54
+ Util.log_error("Token Refresh Failed", store: store)
55
+ raise Procore::OAuthError.new(
56
+ "Unable to refresh the access token. Perhaps the Procore API is " \
57
+ "down or your access token store is misconfigured. Either " \
58
+ "way, you should clear the store and prompt the user to sign in " \
59
+ "again.",
60
+ )
61
+ end
45
62
  end
46
63
 
47
- def api_version
48
- options[:api_version] || 'vapid'
64
+ # @raise [OAuthError] if a token cannot be revoked.
65
+ def revoke
66
+ token = fetch_token
67
+
68
+ begin
69
+ @credentials.revoke(token: token)
70
+ Util.log_info("Token Revocation Successful", store: store)
71
+ rescue RuntimeError
72
+ Util.log_error("Token Revocation Failed", store: store)
73
+ raise Procore::OAuthError.new(
74
+ "Unable to revoke the access token. Perhaps the Procore API is " \
75
+ "down or your access token store is misconfigured. Either " \
76
+ "way, you should clear the store and prompt the user to sign in " \
77
+ "again.",
78
+ )
79
+ end
49
80
  end
50
81
 
51
- # @raise [OAuthError] if the store does not have a token stored in it prior
52
- # to making a request.
53
- # @raise [OAuthError] if a token cannot be refreshed.
54
- # @raise [OAuthError] if incorrect credentials have been supplied.
55
- def access_token
56
- token = store.fetch
82
+ private
83
+
84
+ def base_api_path
85
+ "#{options[:host]}"
86
+ end
57
87
 
88
+ # @raise [OAuthError] if the store does not have a token stored.
89
+ def fetch_token
90
+ token = store.fetch
58
91
  if token.nil? || token.invalid?
59
92
  raise Procore::MissingTokenError.new(
60
93
  "Unable to retreive an access token from the store. Double check " \
@@ -62,28 +95,15 @@ module Procore
62
95
  "before attempting to make API requests",
63
96
  )
64
97
  end
98
+ token
99
+ end
65
100
 
101
+ def access_token
102
+ token = fetch_token
66
103
  if token.expired?
67
104
  Util.log_info("Token Expired", store: store)
68
- begin
69
- token = @credentials.refresh(
70
- token: token.access_token,
71
- refresh: token.refresh_token,
72
- )
73
-
74
- Util.log_info("Token Refresh Successful", store: store)
75
- store.save(token)
76
- rescue RuntimeError
77
- Util.log_error("Token Refresh Failed", store: store)
78
- raise Procore::OAuthError.new(
79
- "Unable to refresh the access token. Perhaps the Procore API is " \
80
- "down or the your access token store is misconfigured. Either " \
81
- "way, you should clear the store and prompt the user to sign in " \
82
- "again.",
83
- )
84
- end
105
+ refresh
85
106
  end
86
-
87
107
  token.access_token
88
108
  end
89
109
  end
@@ -32,6 +32,15 @@ module Procore
32
32
  # @return [String]
33
33
  attr_accessor :host
34
34
 
35
+ # @!attribute [rw] default_version
36
+ # @note defaults to Defaults::DEFAULT_VERSION
37
+ #
38
+ # The default API version to use if none is specified in the request.
39
+ # Should be either "v1.0" (recommended) or "vapid" (legacy).
40
+ #
41
+ # @return [String]
42
+ attr_accessor :default_version
43
+
35
44
  # @!attribute [rw] logger
36
45
  # @note defaults to nil
37
46
  #
@@ -96,6 +105,7 @@ module Procore
96
105
  @max_retries = 1
97
106
  @timeout = 1.0
98
107
  @user_agent = Procore::Defaults::USER_AGENT
108
+ @default_version = Procore::Defaults::DEFAULT_VERSION
99
109
  end
100
110
  end
101
111
  end
@@ -4,7 +4,7 @@ module Procore
4
4
  # Specifies some sensible defaults for certain configurations + clients
5
5
  class Defaults
6
6
  # Default API endpoint
7
- API_ENDPOINT = "https://app.procore.com".freeze
7
+ API_ENDPOINT = "https://api.procore.com".freeze
8
8
 
9
9
  # Default User Agent header string
10
10
  USER_AGENT = "Procore Ruby Gem #{Procore::VERSION}".freeze
@@ -12,10 +12,14 @@ module Procore
12
12
  # Default size to use for batch requests
13
13
  BATCH_SIZE = 500
14
14
 
15
+ # Default API version to use
16
+ DEFAULT_VERSION = "v1.0"
17
+
15
18
  def self.client_options
16
19
  {
17
20
  host: Procore.configuration.host,
18
21
  user_agent: Procore.configuration.user_agent,
22
+ default_version: Procore.configuration.default_version,
19
23
  }
20
24
  end
21
25
  end
@@ -19,6 +19,7 @@ module Procore
19
19
  RestClient::ServerBrokeConnection,
20
20
  ].freeze
21
21
  # @param path [String] URL path
22
+ # @param version [String] API version
22
23
  # @param query [Hash] Query options to pass along with the request
23
24
  # @option options [Hash] :company_id
24
25
  #
@@ -26,8 +27,8 @@ module Procore
26
27
  # client.get("my_open_items", query: { per_page: 5, filter: {} })
27
28
  #
28
29
  # @return [Response]
29
- def get(path, query: {}, options: {})
30
- full_path = full_path(path)
30
+ def get(path, version: nil, query: {}, options: {})
31
+ full_path = full_path(path, version)
31
32
 
32
33
  Util.log_info(
33
34
  "API Request Initiated",
@@ -47,6 +48,7 @@ module Procore
47
48
  end
48
49
 
49
50
  # @param path [String] URL path
51
+ # @param version [String] API version
50
52
  # @param body [Hash] Body parameters to send with the request
51
53
  # @param options [Hash] Extra request options
52
54
  # @option options [String] :idempotency_token | :company_id
@@ -59,8 +61,8 @@ module Procore
59
61
  # )
60
62
  #
61
63
  # @return [Response]
62
- def post(path, body: {}, options: {})
63
- full_path = full_path(path)
64
+ def post(path, version: nil, body: {}, options: {})
65
+ full_path = full_path(path, version)
64
66
 
65
67
  Util.log_info(
66
68
  "API Request Initiated",
@@ -81,6 +83,7 @@ module Procore
81
83
  end
82
84
 
83
85
  # @param path [String] URL path
86
+ # @param version [String] API version
84
87
  # @param body [Hash] Body parameters to send with the request
85
88
  # @param options [Hash] Extra request options
86
89
  # @option options [String] :idempotency_token | :company_id
@@ -89,8 +92,8 @@ module Procore
89
92
  # client.put("dashboards/1/users", body: [1,2,3], options: { company_id: 1 })
90
93
  #
91
94
  # @return [Response]
92
- def put(path, body: {}, options: {})
93
- full_path = full_path(path)
95
+ def put(path, version: nil, body: {}, options: {})
96
+ full_path = full_path(path, version)
94
97
 
95
98
  Util.log_info(
96
99
  "API Request Initiated",
@@ -111,6 +114,7 @@ module Procore
111
114
  end
112
115
 
113
116
  # @param path [String] URL path
117
+ # @param version [String] API version
114
118
  # @param body [Hash] Body parameters to send with the request
115
119
  # @param options [Hash] Extra request options
116
120
  # @option options [String] :idempotency_token | :company_id
@@ -123,8 +127,8 @@ module Procore
123
127
  # )
124
128
  #
125
129
  # @return [Response]
126
- def patch(path, body: {}, options: {})
127
- full_path = full_path(path)
130
+ def patch(path, version: nil, body: {}, options: {})
131
+ full_path = full_path(path, version)
128
132
 
129
133
  Util.log_info(
130
134
  "API Request Initiated",
@@ -145,6 +149,7 @@ module Procore
145
149
  end
146
150
 
147
151
  # @param path [String] URL path
152
+ # @param version [String] API version
148
153
  # @param body [Hash] Body parameters to send with the request
149
154
  # @param options [Hash] Extra request options
150
155
  # @option options [String | Integer] :company_id | :batch_size
@@ -166,8 +171,8 @@ module Procore
166
171
  # )
167
172
  #
168
173
  # @return [Response]
169
- def sync(path, body: {}, options: {})
170
- full_path = full_path(path)
174
+ def sync(path, version: nil, body: {}, options: {})
175
+ full_path = full_path(path, version)
171
176
 
172
177
  batch_size = options[:batch_size] ||
173
178
  Procore.configuration.default_batch_size
@@ -183,7 +188,7 @@ module Procore
183
188
  batch_size: batch_size,
184
189
  )
185
190
 
186
- groups = body[:updates].in_groups_of(batch_size, false)
191
+ groups = body[:updates].each_slice(batch_size).to_a
187
192
 
188
193
  responses = groups.map do |group|
189
194
  batched_body = body.merge(updates: group)
@@ -206,11 +211,11 @@ module Procore
206
211
  code: 200,
207
212
  request: responses.last&.request,
208
213
  request_body: body,
209
- api_version: api_version,
210
214
  )
211
215
  end
212
216
 
213
217
  # @param path [String] URL path
218
+ # @param version [String] API version
214
219
  # @param query [Hash] Query options to pass along with the request
215
220
  # @option options [String] :company_id
216
221
  #
@@ -218,8 +223,8 @@ module Procore
218
223
  # client.delete("users/1", query: {}, options: {})
219
224
  #
220
225
  # @return [Response]
221
- def delete(path, query: {}, options: {})
222
- full_path = full_path(path)
226
+ def delete(path, version: nil, query: {}, options: {})
227
+ full_path = full_path(path, version)
223
228
 
224
229
  Util.log_info(
225
230
  "API Request Initiated",
@@ -270,7 +275,6 @@ module Procore
270
275
  code: result.code,
271
276
  request: result.request,
272
277
  request_body: request_body,
273
- api_version: api_version
274
278
  )
275
279
 
276
280
  case result.code
@@ -339,6 +343,8 @@ module Procore
339
343
  "Accepts" => "application/json",
340
344
  "Authorization" => "Bearer #{access_token}",
341
345
  "Content-Type" => "application/json",
346
+ "Procore-Sdk-Version" => Procore::VERSION,
347
+ "Procore-Sdk-Language" => "ruby",
342
348
  "User-Agent" => Procore.configuration.user_agent,
343
349
  }.tap do |headers|
344
350
  if options[:idempotency_token]
@@ -363,8 +369,15 @@ module Procore
363
369
  RestClient::Payload::has_file?(body)
364
370
  end
365
371
 
366
- def full_path(path)
367
- File.join(base_api_path, path).to_s
372
+ def full_path(path, version)
373
+ version ||= options[:default_version]
374
+ if version == "vapid"
375
+ File.join(base_api_path, "vapid", path)
376
+ elsif /\Av\d+\.\d+\z/.match?(version)
377
+ File.join(base_api_path, "rest", version, path)
378
+ else
379
+ raise Procore::InvalidRequestError.new "#{version} is an invalid Procore API version"
380
+ end
368
381
  end
369
382
  end
370
383
  end
@@ -45,12 +45,11 @@ module Procore
45
45
  # @return [Integer] Status Code returned from Procore API.
46
46
  # @!attribute [r] pagination
47
47
  # @return [Hash<Symbol, String>] Pagination URLs
48
- attr_reader :headers, :code, :pagination, :request, :request_body, :api_version
48
+ attr_reader :headers, :code, :pagination, :request, :request_body
49
49
 
50
- def initialize(body:, headers:, code:, request:, request_body:, api_version: 'vapid')
50
+ def initialize(body:, headers:, code:, request:, request_body:)
51
51
  @code = code
52
52
  @headers = headers
53
- @api_version = api_version
54
53
  @pagination = parse_pagination
55
54
  @request = request
56
55
  @request_body = request_body
@@ -73,7 +72,7 @@ module Procore
73
72
 
74
73
  def parse_pagination
75
74
  headers[:link].to_s.split(", ").map(&:strip).reduce({}) do |links, link|
76
- url, name = link.match(/#{api_version}\/(.*?)>; rel="(\w+)"/).captures
75
+ url, name = link.match(/(?:vapid|rest\/.*?)\/(.*?)>; rel="(\w+)"/).captures
77
76
  links.merge!(name.to_sym => url)
78
77
  end
79
78
  end
@@ -1,3 +1,3 @@
1
1
  module Procore
2
- VERSION = "0.8.8".freeze
2
+ VERSION = "1.1.3".freeze
3
3
  end
data/procore-1.1.1.gem ADDED
Binary file
data/procore.gemspec CHANGED
@@ -32,6 +32,8 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "rake"
33
33
  spec.add_development_dependency "redis"
34
34
  spec.add_development_dependency "rubocop"
35
+ spec.add_development_dependency "rubocop-performance"
36
+ spec.add_development_dependency "rubocop-rails"
35
37
  spec.add_development_dependency "sqlite3"
36
38
  spec.add_development_dependency "webmock"
37
39
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: procore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.8
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Procore Engineering
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-17 00:00:00.000000000 Z
11
+ date: 2021-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -150,6 +150,34 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-performance
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-rails
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: sqlite3
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -255,6 +283,7 @@ files:
255
283
  - lib/procore/response.rb
256
284
  - lib/procore/util.rb
257
285
  - lib/procore/version.rb
286
+ - procore-1.1.1.gem
258
287
  - procore.gemspec
259
288
  homepage: https://github.com/procore/ruby-sdk
260
289
  licenses:
@@ -275,7 +304,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
275
304
  - !ruby/object:Gem::Version
276
305
  version: '0'
277
306
  requirements: []
278
- rubygems_version: 3.0.3
307
+ rubyforge_project:
308
+ rubygems_version: 2.6.14
279
309
  signing_key:
280
310
  specification_version: 4
281
311
  summary: Procore Ruby Gem