shotgrid_api_ruby 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in shotgrid_api_ruby.gemspec
6
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A sample Guardfile
4
+ # More info at https://github.com/guard/guard#readme
5
+
6
+ ## Uncomment and set this to only include directories you want to watch
7
+ # directories %w(app lib config test spec features) \
8
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
9
+
10
+ ## Note: if you are using the `directories` clause above and you are not
11
+ ## watching the project directory ('.'), then you will want to move
12
+ ## the Guardfile to a watched dir and symlink it back, e.g.
13
+ #
14
+ # $ mkdir config
15
+ # $ mv Guardfile config/
16
+ # $ ln -s config/Guardfile .
17
+ #
18
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
19
+
20
+ # Note: The cmd option is now required due to the increasing number of ways
21
+ # rspec may be run, below are examples of the most common uses.
22
+ # * bundler: 'bundle exec rspec'
23
+ # * bundler binstubs: 'bin/rspec'
24
+ # * spring: 'bin/rspec' (This will use spring if running and you have
25
+ # installed the spring binstubs per the docs)
26
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
27
+ # * 'just' rspec: 'rspec'
28
+
29
+ guard :rspec, cmd: "bundle exec rspec" do
30
+ require "guard/rspec/dsl"
31
+ dsl = Guard::RSpec::Dsl.new(self)
32
+
33
+ # Feel free to open issues for suggestions and improvements
34
+
35
+ # RSpec files
36
+ rspec = dsl.rspec
37
+ watch(rspec.spec_helper) { rspec.spec_dir }
38
+ watch(rspec.spec_support) { rspec.spec_dir }
39
+ watch(rspec.spec_files)
40
+
41
+ # map lib files to corresponding file
42
+ watch(%r{lib/(.*)/([^/]*).rb}) { |m| rspec.spec.call("#{m[1]}/#{m[2]}") }
43
+
44
+ # Ruby files
45
+ ruby = dsl.ruby
46
+ dsl.watch_spec_files_for(ruby.lib_files)
47
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Denis <Zaratan> Pasin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,470 @@
1
+ # ShotgridApiRuby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/shotgrid_api_ruby.svg)](https://badge.fury.io/rb/shotgrid_api_ruby)
4
+ ![Test and Release badge](https://github.com/shotgunsoftware/shotgrid_api_ruby/workflows/Test%20and%20Release/badge.svg)
5
+
6
+ A gem to integrate with shotgrid REST API easily.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'shotgrid_api_ruby'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install shotgrid_api_ruby
23
+
24
+ ## Usage
25
+
26
+ ### Client instantiation
27
+
28
+ For creating a new client you need to provide two values.
29
+
30
+ - One to identify the shotgrid site:
31
+ - Can be `shotgun_site`: which is the `xxx` part in `https://xxx.shotgunstudio.com`
32
+ - Can be `shotgrid_site`: which is the `xxx` part in `https://xxx.shotgrid.autodesk.com`
33
+ - Can be `site_url`: which is the full url to your site
34
+ - One to `auth` you see _Authentication_ lower in this guide.
35
+
36
+ Example:
37
+
38
+ ```ruby
39
+ client = ShotgridApiRuby.new(shotgrid_site: 'i-love-shotgrid', auth: {client_id: 'my_nice_script', client_secret: 'CantTouchThis'})
40
+ ```
41
+
42
+ ### Authentication
43
+
44
+ Any kind of authentication specified [here](https://developer.shotgunsoftware.com/rest-api/#authentication) is implemented
45
+
46
+ #### Client Credentials
47
+
48
+ ```ruby
49
+ client = ShotgridApiRuby.new(shotgrid_site: 'xxx', auth: {client_id: 'script_name', client_secret: 'script_secret'})
50
+ ```
51
+
52
+ #### Password Credentials
53
+
54
+ ```ruby
55
+ client = ShotgridApiRuby.new(shotgrid_site: 'xxx', auth: {username: 'login', password: 'password'})
56
+ ```
57
+
58
+ #### Session Token
59
+
60
+ **We highly advise not using this for a long term script as this won't be a stable value over time**
61
+
62
+ ```ruby
63
+ client = ShotgridApiRuby.new(shotgrid_site: 'xxx', auth: {session_token: 'session_token'})
64
+ ```
65
+
66
+ #### Refresh Token
67
+
68
+ **We highly advise not using this for a long term script as this won't be a stable value over time**
69
+
70
+ ```ruby
71
+ client = ShotgridApiRuby.new(shotgrid_site: 'xxx', auth: {refresh_token: 'refresh_token'})
72
+ ```
73
+
74
+ ### Server Infos
75
+
76
+ Get general server infos:
77
+
78
+ ```ruby
79
+ client.server_info.get
80
+
81
+ # #<OpenStruct
82
+ shotgun_version="v8.6.0.0-dev (build 12864de)",
83
+ api_version="v1",
84
+ shotgun_version_number="8.6.0.0-dev",
85
+ shotgun_build_number="12864de",
86
+ portfolio_version="UNKNOWN",
87
+ unified_login_flow_enabled=true,
88
+ user_authentication_method="default">
89
+ ```
90
+
91
+ ### Preferences
92
+
93
+ Get some preferences infos:
94
+
95
+ ```ruby
96
+ prefs = client.preferences.get
97
+ prefs.to_h.keys
98
+
99
+ # [:format_date_fields,
100
+ # :date_component_order,
101
+ # :format_time_hour_fields,
102
+ # :format_currency_fields_display_dollar_sign,
103
+ # :format_currency_fields_decimal_options,
104
+ # :format_currency_fields_negative_options,
105
+ # :format_number_fields,
106
+ # :format_float_fields,
107
+ # :format_float_fields_rounding,
108
+ # :format_footage_fields,
109
+ # :support_local_storage,
110
+ # :view_master_settings,
111
+ # :duration_units,
112
+ # :hours_per_day,
113
+ # :last_day_work_week]
114
+ ```
115
+
116
+ ### Entities
117
+
118
+ Querying entities is done by accessing the named method
119
+
120
+ ```ruby
121
+ client.assets # => ShotgridApiRuby::Entities …
122
+ ```
123
+
124
+ As entities can be user defined the client will try to answer to any unknown type with an entity call so any of those calls will returns the same thing:
125
+
126
+ ```ruby
127
+ client.assets
128
+ client.asset
129
+ client.entities("Asset")
130
+ client.entities(:Assets)
131
+ ```
132
+
133
+ Any not yet implemented call can be accessed through the connection: `client.assets.connection`
134
+
135
+ #### Entity
136
+
137
+ Returned entity will try to behave as nicely as possible.
138
+
139
+ An entity will always answer to:
140
+
141
+ - .type : the type of the entity
142
+ - .id : the id of the entity
143
+ - .relationships : a hash of relationships
144
+ - .links : a hash of links to other entities
145
+ - .attributes : An object answering to any available attributes
146
+
147
+ It will also answer to any method that is present in the attributes:
148
+
149
+ ```ruby
150
+ assets = client.assets.all(fields: 'code')
151
+ assets.first.type # => "Asset"
152
+ assets.first.id # => 726
153
+ assets.first.attributes.code # => "Buck"
154
+ assets.first.code # => "Buck"
155
+ ```
156
+
157
+ ### Search
158
+
159
+ #### all
160
+
161
+ The all call will return all possible entities.
162
+
163
+ ```ruby
164
+ client.assets.all
165
+ ```
166
+
167
+ #### search
168
+
169
+ Does the same thing as `all`
170
+
171
+ #### first
172
+
173
+ Will return only the first entity found (same thing as setting the page_size to 1 and then getting the first result)
174
+
175
+ ```
176
+ client.assets.first
177
+ ```
178
+
179
+ #### arguments
180
+
181
+ ##### fields
182
+
183
+ This attribute describe the wanted fields in the returned entity
184
+
185
+ Can be a string describing wanted fields: `'code'` or `'code,description'`
186
+ Or an array for better readability: `[:code, 'description']`
187
+
188
+ Example:
189
+
190
+ ```ruby
191
+ client.assets.all(fields: [:code, :description])
192
+ ```
193
+
194
+ ##### sort
195
+
196
+ Describe how you want your entities to be sorted.
197
+
198
+ Can be either:
199
+
200
+ - A string: `'code'` or `'code,-description'` (the `-` asking for a descending order)
201
+ - An array for better readability: `[:code, '-description']`
202
+ - A hash for ease of use: `{code: 'asc', description: :desc}`
203
+
204
+ Example:
205
+
206
+ ```ruby
207
+ client.assets.all(fields: [:code, :description], sort: {code: :asc, description: :desc})
208
+ ```
209
+
210
+ ##### logical_operator
211
+
212
+ Default: "and"
213
+
214
+ This will be only used on complex queries. This is how we treat multiple first level conditions.
215
+
216
+ Accepted values: 'and', 'or'
217
+
218
+ ##### filter
219
+
220
+ For simple filters, the filter field is waiting for a hash.
221
+
222
+ Each value is:
223
+
224
+ - A string: then a `is` filter will be used
225
+ - An array: then a `in` filter will be used
226
+
227
+ Example:
228
+
229
+ ```ruby
230
+ client.assets.all(fields: [:code, :description], filter: {code: ['Buck', :Darcy], description: 'I LOVE SG'})
231
+ ```
232
+
233
+ For complex filters, see the documentation [here](https://developer.shotgunsoftware.com/rest-api/#searching).
234
+
235
+ If the filters are complex there's many cases:
236
+
237
+ * If they are a hash containing logical_operator and conditions => we will use them
238
+ * If the filter is **not** a hash => we will use it without translation
239
+ * If the filter is a hash not containing "conditions". We will try to translate this to SG compatible query.
240
+
241
+ Example:
242
+ ```ruby
243
+ client.assets.all(
244
+ filter: {
245
+ project: { id: 2 },
246
+ sg_status_list: ["act", "hld", "omt"]
247
+ },
248
+ )
249
+ # Will be translated to:
250
+ {
251
+ "filters"=>{
252
+ "conditions"=> [
253
+ ["project.Project.id", "is", 2],
254
+ ["sg_status_list", "in", ["act", "hld", "omt"]]
255
+ ],
256
+ "logical_operator"=>"and"
257
+ }
258
+ }
259
+ ```
260
+
261
+ The complexity of calling a different route and passing different headers/body/params will be taken care of automatically.
262
+
263
+ ##### page
264
+
265
+ You can ask for any page size or page number.
266
+
267
+ - `page`: set the page number.
268
+ - `page_size`: set the size of each page.
269
+
270
+ Any of the two can be omited. Their type should be a number but it'll work with a string
271
+
272
+ Example:
273
+
274
+ ```ruby
275
+ client.assets.all(fields: [:code], page: 3, page_size: 10)
276
+ client.assets.all(fields: [:code], page: '3')
277
+ client.assets.all(fields: [:code], page_size: 10)
278
+ ```
279
+
280
+ ##### options
281
+
282
+ Special options can be added:
283
+
284
+ - retired: a flag telling if the returned entities should be retired or not
285
+ - include_archived_projects: a flag telling if the archived projets should be included int the search
286
+
287
+ Example:
288
+
289
+ ```ruby
290
+ client.assets.all(fields: [:code], retired: true)
291
+ client.assets.all(fields: [:code], include_archived_projects: true)
292
+ ```
293
+
294
+ ### Finding one element
295
+
296
+ `find` function on `entities` allow you to get one element in particular.
297
+
298
+ It accepts (all arguments are optional):
299
+
300
+ - fields: string, symbol or array of fields
301
+ - retired: boolean specifying if the record is retired
302
+ - include_archived_projects: boolean specifying if the entity is part of an archived project
303
+
304
+ Example:
305
+
306
+ ```ruby
307
+ client.assets.find(724, fields: [:code, 'description'], retired: false)
308
+ ```
309
+
310
+ ### Create
311
+
312
+ Will create the entity referenced by the id with the following fields.
313
+ If successful, it will return the newly created entity.
314
+
315
+ ```ruby
316
+ client.assets.create(code: 'New Asset', project: {type: 'Project', id: 63})
317
+ ```
318
+
319
+ ### Update
320
+
321
+ Will update the entity referenced by the id with the following fields.
322
+ If successful, it will return the modified entity.
323
+
324
+ ```ruby
325
+ client.assets.update(1226, code: 'Updated Asset', sg_status_list: 'fin')
326
+ ```
327
+
328
+ ### Delete
329
+
330
+ Will destroys the entity referenced by the id. Will return true if successful.
331
+
332
+ ```ruby
333
+ client.assets.delete(1226)
334
+ ```
335
+
336
+ ### Revive
337
+
338
+ Will try to revive the entity referenced by the id. Will return true if successful.
339
+
340
+ ```ruby
341
+ client.assets.revive(1226)
342
+ ```
343
+
344
+ ### Summarize
345
+
346
+ Will summarize data for an entity type.
347
+
348
+ Example:
349
+ ```ruby
350
+ # Simplest example
351
+ client.assets.summarize(summary_fields: {id: :count})
352
+
353
+ # Full complex example
354
+ client.assets.summarize(
355
+ filter: { project: { id: 122 }, sg_status_list: :act },
356
+ logical_operator: 'or',
357
+ include_archived_projects: true,
358
+ grouping: {
359
+ code: {direction: :desc, type: 'exact'}
360
+ },
361
+ summary_fields: { id: :count }
362
+ )
363
+
364
+ # Raw shotgrid queries
365
+ client.assets.summarize(
366
+ grouping: [
367
+ {
368
+ "field": "sg_asset_type",
369
+ "type": "exact",
370
+ "direction": "asc"
371
+ }
372
+ ],
373
+ summary_fields: [
374
+ {
375
+ "field": "id",
376
+ "type": "count"
377
+ }
378
+ ],
379
+ )
380
+ ```
381
+
382
+ It accepts the same `filter` and `logical_operator` as a `search` will.
383
+
384
+ #### Summary fields
385
+
386
+ Those can have two forms:
387
+
388
+ ##### The normal API form
389
+
390
+ You need to supply the summary_fields as an array and it will be passed directly to the SG REST API
391
+
392
+ #### The convenient form
393
+
394
+ Using an array isn't very convenient most of the time. You can use a hash instead and it will be translated into a "SG summary_fields array".
395
+
396
+ Each key of the hash is the field name and the corresponding value is the type a summary you want (can be a string or a symbol)
397
+
398
+ #### Grouping
399
+
400
+ Those can have two forms:
401
+
402
+ ##### The normal API form
403
+
404
+ You need to supply the grouping as an array and it will be passed directly to the SG REST API
405
+
406
+ #### The convenient form
407
+
408
+ Using an array isn't very convenient most of the time. You can use a hash instead and it will be translated into a "SG grouping array".
409
+
410
+ Each key of the hash is the field name and the corresponding value can either be :
411
+ * A String/Symbol and then will be used a a direction. The type will be 'exact'
412
+ * A Hash with optional 'type' and 'direction' keys. If a key is not specified it will be 'exact' and 'asc' respectively.
413
+
414
+ ### Count
415
+
416
+ This is a helper for more a readable count summary. This can be passed `filter` and `logical_operator`.
417
+
418
+ Example:
419
+
420
+ ```ruby
421
+ client.assets.count
422
+
423
+ # This will be equivalent as doing:
424
+ client.assets.summarize(summary_fields: [{type: :record_count, field: :id}])
425
+ ```
426
+
427
+ ### Schema
428
+
429
+ Those calls allow to inspect the schema for a shotgrid site.
430
+
431
+ #### Entity
432
+
433
+ ```ruby
434
+ client.assets.schema
435
+ ```
436
+
437
+ #### Entity fields
438
+
439
+ Fetch the different fields available on an entity type and their definition.
440
+
441
+ ```ruby
442
+ fields = client.assets.fields
443
+ fields.code.name # => "Asset Name"
444
+ fields.code.properties.summary_default # => "none"
445
+ ```
446
+
447
+ ### Non implemented calls
448
+
449
+ All calls which are not yet implemented can be done through the `connection` method. This method will still take care of the authentication for you.
450
+
451
+ ```ruby
452
+ client = ShotgridApiRuby.new(…)
453
+ client.connection.get('/entity/assets') # => #<Faraday::Response:xxx @on_complete_callbacks=[], @env=#<Faraday::Env @method=:get @body="{\"data\":[{\"type\":\"Asset\",\"attributes\":{},\"relationships\":{},\"id\":726 …
454
+ ```
455
+
456
+ ## Development
457
+
458
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
459
+
460
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
461
+
462
+ Every commit/push is checked by overcommit.
463
+
464
+ ## Contributing
465
+
466
+ Bug reports and pull requests are welcome on GitHub at https://github.com/shotgunsoftware/shotgrid_api_ruby.
467
+
468
+ ## License
469
+
470
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).