procore 0.8.8 → 1.0.0

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
2
  SHA256:
3
- metadata.gz: cc64539748539d38af7f3dedc9a825ae8dff0f84939a53cddf1bf124dcba6c0a
4
- data.tar.gz: 3a5bbe135e42bbf3d05e7d68a45829bf6dc185334e73ea579ca88cee66ccb757
3
+ metadata.gz: ab6a771f9ecbd227e500591c59381e08e70b1ad3cea2f82e767b4de2d88664b3
4
+ data.tar.gz: 1159fa494f5d38ce2d0a0fbcbdb465bf6203e8989a96acf3bcceab915ea9dbac
5
5
  SHA512:
6
- metadata.gz: f3450511913a6f4c6933a263dfc05d4b564f49978bc334ae043100f4b028b3191dbc486ef0f42bc623da510e3922789a6abbc8120d8f7539e1164c06f91452c5
7
- data.tar.gz: 2f82f682587398a82831a024a86fff4c986edc4927828a4fb478ef58a6d3b45f080a3dc9822aaf4c7a1a1ac212d7bf53b829efeaa5286d246d86be305a8fe92e
6
+ metadata.gz: e1c9f942d9c8223df00bff8c67b366adc85be3224d2a6ef41ee4e345d40cba8cc0ca71fe0361ff094be1ba358d3ad7ead40fc99d36bba8e5edac0dfc19932c57
7
+ data.tar.gz: afb9275ad4ec9b1396f3f7bed77317eb39b8e6cacf5d82dc77b38e9a934491e439795fe7df432d27fdc337800b7343327f1cb9d7b70c072ed72244bcd41d6a0a
@@ -1,5 +1,9 @@
1
+ require:
2
+ - rubocop-rails
3
+ - rubocop-performance
4
+
1
5
  AllCops:
2
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.4
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
@@ -1,4 +1,52 @@
1
- ## Unreleased
1
+ ## 1.0.0 (January 5, 2021)
2
+
3
+ * Adds support for API versioning
4
+
5
+ *Nate Baer*
6
+
7
+ ### Upgrading
8
+
9
+ As of v1.0.0, this gem now defaults to making requests against Procore's new
10
+ Rest v1.0 resources, instead of the now deprecated `/vapid` namespace. Example:
11
+
12
+ ```ruby
13
+ # Previously makes a request to
14
+ client.get("me")
15
+ => app.procore.com/vapid/me
16
+
17
+ # In 1.0.0
18
+ client.get("me")
19
+ => app.procore.com/rest/v1.0/me
20
+ ```
21
+
22
+ To keep the legacy behavior, set the new `default_version` configuration option.
23
+ Note, that Rest v1.0 is a superset of the Vapid Api - there are no breaking
24
+ changes. The Vapid API will be decommissioned in December 2021.
25
+
26
+ [Read more here](https://developers.procore.com/documentation/vapid-deprecation)
27
+
28
+ ```ruby
29
+ Procore.configure do |config|
30
+ ...
31
+ # Defaults to "v1.0"
32
+ config.default_version = "vapid"
33
+ ...
34
+ end
35
+ ```
36
+
37
+ All the request methods (`get`, `post`, `patch`, `put`, `delete`, `sync`) now
38
+ accept an optional version parameter to specify the version at request time.
39
+
40
+ ```ruby
41
+ client.get("me")
42
+ => https://app.procore.com/rest/v1.0/me
43
+
44
+ client.get("me", version: "v1.1")
45
+ => https://app.procore.com/rest/v1.1/me
46
+
47
+ client.get("me", version: "vapid")
48
+ => https://app.procore.com/vapid/me
49
+ ```
2
50
 
3
51
  ## 0.8.8 (October 17, 2019)
4
52
 
data/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #### Table of Contents
6
6
  - [Installation](#installation)
7
+ - [1.0.0 Release](#1.0.0-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,27 @@ 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://app.procore.com/rest/v1.0/me` |
69
+ | `client.get("me", version: "v1.1")` | `https://app.procore.com/rest/v1.1/me` |
70
+ | `client.get("me", version: "vapid")` | `https://app.procore.com/vapid/me` |
58
71
 
59
72
  Example Usage:
60
73
 
@@ -72,6 +85,19 @@ companies = client.get("companies")
72
85
  companies.first[:name] #=> "Procore Company 1"
73
86
  ```
74
87
 
88
+ To use Procore's older API Vapid by default, the default version can be set in
89
+ either the Gem's [configuration](https://github.com/procore/ruby-sdk#configuration)
90
+ or the client's `options` hash:
91
+
92
+ ```ruby
93
+ client = Procore::Client.new(
94
+ ...
95
+ options {
96
+ default_version: "vapid"
97
+ }
98
+ )
99
+ ```
100
+
75
101
  ## Usage
76
102
 
77
103
  The first step is to place the user's token into the store. For this example,
@@ -324,6 +350,10 @@ Procore.configure do |config|
324
350
  # are desired, 4 requests will be made. Note, the maximum size is 1000.
325
351
  config.default_batch_size = 500
326
352
 
353
+ # The default API version to use if none is specified in the request.
354
+ # Should be either "v1.0" (recommended) or "vapid" (legacy).
355
+ config.default_version = "v1.0"
356
+
327
357
  # Integer: Number of times to retry a failed API call. Reasons an API call
328
358
  # could potentially fail:
329
359
  # 1. Service is briefly down or unreachable
@@ -41,11 +41,7 @@ module Procore
41
41
  private
42
42
 
43
43
  def base_api_path
44
- "#{options[:host]}/#{api_version}"
45
- end
46
-
47
- def api_version
48
- options[:api_version] || 'vapid'
44
+ "#{options[:host]}"
49
45
  end
50
46
 
51
47
  # @raise [OAuthError] if the store does not have a token stored in it prior
@@ -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
@@ -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
@@ -363,8 +367,15 @@ module Procore
363
367
  RestClient::Payload::has_file?(body)
364
368
  end
365
369
 
366
- def full_path(path)
367
- File.join(base_api_path, path).to_s
370
+ def full_path(path, version)
371
+ version ||= options[:default_version]
372
+ if version == "vapid"
373
+ File.join(base_api_path, "vapid", path)
374
+ elsif /\Av\d+\.\d+\z/.match?(version)
375
+ File.join(base_api_path, "rest", version, path)
376
+ else
377
+ raise ArgumentError.new "'#{version}' is an invalid Procore API version"
378
+ end
368
379
  end
369
380
  end
370
381
  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.0.0".freeze
3
3
  end
@@ -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.0.0
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-01-05 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
@@ -275,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
275
303
  - !ruby/object:Gem::Version
276
304
  version: '0'
277
305
  requirements: []
278
- rubygems_version: 3.0.3
306
+ rubygems_version: 3.1.4
279
307
  signing_key:
280
308
  specification_version: 4
281
309
  summary: Procore Ruby Gem