procore 0.8.8 → 1.0.0

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: 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