transloadit 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +3 -1
  3. data/.travis.yml +4 -4
  4. data/CHANGELOG.md +26 -0
  5. data/LICENSE +1 -1
  6. data/README.md +141 -16
  7. data/examples/README.md +185 -0
  8. data/examples/basic/audio-concat-transcoder.rb +40 -0
  9. data/examples/basic/audio-transcoder.rb +37 -0
  10. data/examples/basic/image-transcoder.rb +27 -0
  11. data/examples/basic/main.rb +69 -0
  12. data/examples/basic/media-transcoder.rb +13 -0
  13. data/lib/transloadit.rb +31 -0
  14. data/lib/transloadit/api_model.rb +73 -0
  15. data/lib/transloadit/assembly.rb +103 -63
  16. data/lib/transloadit/exception.rb +27 -0
  17. data/lib/transloadit/request.rb +23 -41
  18. data/lib/transloadit/response/assembly.rb +25 -0
  19. data/lib/transloadit/template.rb +63 -0
  20. data/lib/transloadit/version.rb +1 -1
  21. data/test/fixtures/cassettes/create_template.yml +48 -0
  22. data/test/fixtures/cassettes/delete_template.yml +44 -0
  23. data/test/fixtures/cassettes/fetch_assemblies.yml +44 -0
  24. data/test/fixtures/cassettes/fetch_assembly_notifications.yml +44 -0
  25. data/test/fixtures/cassettes/fetch_assembly_ok.yml +36 -0
  26. data/test/fixtures/cassettes/fetch_billing.yml +44 -0
  27. data/test/fixtures/cassettes/{fetch_bored.yml → fetch_root.yml} +6 -6
  28. data/test/fixtures/cassettes/fetch_template.yml +44 -0
  29. data/test/fixtures/cassettes/fetch_templates.yml +44 -0
  30. data/test/fixtures/cassettes/rate_limit_fail.yml +105 -0
  31. data/test/fixtures/cassettes/rate_limit_succeed.yml +79 -0
  32. data/test/fixtures/cassettes/replay_assembly.yml +49 -0
  33. data/test/fixtures/cassettes/replay_assembly_notification.yml +48 -0
  34. data/test/fixtures/cassettes/submit_assembly.yml +1 -36
  35. data/test/fixtures/cassettes/update_template.yml +48 -0
  36. data/test/test_helper.rb +4 -0
  37. data/test/unit/test_transloadit.rb +14 -1
  38. data/test/unit/transloadit/test_api.rb +50 -0
  39. data/test/unit/transloadit/test_assembly.rb +178 -47
  40. data/test/unit/transloadit/test_request.rb +28 -20
  41. data/test/unit/transloadit/test_response.rb +44 -0
  42. data/test/unit/transloadit/test_template.rb +118 -0
  43. data/transloadit.gemspec +3 -3
  44. metadata +70 -33
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTY2M2FlNjUwMWY0M2Q4MDFkNzZiYzdmZWExOTFhZDZlM2U3ODE5OQ==
5
- data.tar.gz: !binary |-
6
- ZGYzNGU5ODZhNWE4N2ZkZGU4YWJjYWViMTE0MmE3MTdlMmNhMTljNA==
2
+ SHA1:
3
+ metadata.gz: d66c5ecc22a6dc2615019e622dca2f112ac7cda1
4
+ data.tar.gz: 608bfd88a07b6eb14a53e32d028851d86aa0a484
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZTc3OWI0ZTM5NzRkNTQzOTExODZlOTFiMzExMTM3NjAwYWRhMDllZjI5ODYx
10
- NjU0OWUxOWMzYzJhZGRmYzM0MzNlMTIxZTZiNDgzNmQ5ZjE2NDFhYzM4NDNh
11
- NDFmODExYmIxZTMyNDc3NmRjNmExOTAwZDJjMmY1ZjI0OWM1ZDA=
12
- data.tar.gz: !binary |-
13
- MTEwNWJjNjEyNGFhYWI4M2IxMWEyYzgwNzBiMzE1YWZiZjk5ZjQyNmViMmY2
14
- NGM0ZDg0OTVjOTE5YzE0NDNjOTgxODk0NGUyZDU0MmVhNzk0NjE2M2I0Nzlh
15
- Yjg4ZGFjNWFiMDMzNDgxMDQ5YjE3OGQ1ZmE4M2E5Yjk3YTEwYmQ=
6
+ metadata.gz: e7577eb0f960c787517359bfff2f7aab1d16c0e13c2245c408a4bf8cb8efcde79af19d271afdf9aa5affc37d691b00ef14fd8a8f066fead33055b119d3b235b7
7
+ data.tar.gz: dfafe3de4fa8ea264c266293116f2358928b6dc7170930484ae336a7159e91f66dd10c5586ce0e3d71141e9181953945490469583043b8c8a0226e0ef425d64c
data/.gitignore CHANGED
@@ -2,7 +2,7 @@
2
2
  .rvmrc
3
3
  .yardoc
4
4
  .ruby-version
5
-
5
+ .idea/
6
6
  Gemfile.lock
7
7
 
8
8
  coverage
@@ -10,3 +10,5 @@ doc
10
10
  pkg
11
11
 
12
12
  transloadit-*.gem
13
+
14
+ .DS_Store
@@ -1,13 +1,13 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 1.9.2
5
- - 1.9.3
6
- - 2.0.0
7
4
  - 2.1.0
8
5
  - 2.2.0
9
6
  - 2.3.0
10
7
  - rbx-2
11
- - jruby-19mode
12
8
  - jruby-9.0.0.0
13
9
  script: "COVERAGE=false bundle exec rake test"
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: rbx-2
13
+
@@ -1,3 +1,29 @@
1
+ ### 2.0.0 / 2016-12-03 ###
2
+
3
+ * Drop support for EOL'd Ruby 1.9.x and Ruby 2.0, please use version 1.2.0 if you need support for older
4
+ Ruby versions.
5
+ * Fix compatibility to Ruby >=2.1 and Rails 5.
6
+ * Remove bored instance logic (thanks @ifedapoolarewaju for the PR). This shouldn't affect users at all and removes
7
+ the need for another HTTP request before the actual HTTP request.
8
+ * We now have the `transloadit.bill` method to retrieve billing reports. (@ifedapoolarewaju)
9
+ * Deprecate `assembly.submit!` method for `assembly.create!`. This shouldn't affect users as the `submit!` method remains
10
+ as an alias for `create!`. (@ifedapoolarewaju)
11
+ * Add support for new `assembly` methods (Thanks @ifedapoolarewaju):
12
+ * list to get a list of all assemblies.
13
+ * get to retrieve a particular assembly. Requires assembly id to be passed as argument.
14
+ * replay to replay a particular assembly. Requires assembly id to be passed as argument.
15
+ * get_notifications to get a list of all assembly notifications.
16
+ * replay_notification to replay the notification of a particular assembly. Requires assembly id to be passed as argument.
17
+ * We now have a Template api with the following methods:
18
+ * create to create a new template.
19
+ * list to get a list of all templates.
20
+ * get to retrieve a particular template.
21
+ * update to update a particular template.
22
+ * delete to delete a particular template.
23
+ * Add rate limit feature to implicitly retry assembly creation when the rate limit is reached.
24
+ * Add `assembly.reload_until_finished!` which calls `reload!` once per second until assembly is finished (@gbuesing)
25
+ * Added example files with a [small tutorial](examples/README.md) in `examples` (@jasonaibrahim)
26
+
1
27
  ### 1.2.0 / 2015-12-28 ###
2
28
 
3
29
  * allow custom fields to be passed to Transloadit and received back in the response (thanks @Acconut for the pull request)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2015 Transloadit Ltd.
3
+ Copyright (c) 2016 Transloadit Ltd.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
data/README.md CHANGED
@@ -67,12 +67,10 @@ assembly = transloadit.assembly(
67
67
  :steps => [ resize, store ]
68
68
  )
69
69
 
70
- response = assembly.submit! open('lolcat.jpg')
70
+ response = assembly.create! open('lolcat.jpg')
71
71
 
72
- # loop until processing is finished
73
- until response.finished?
74
- sleep 1; response.reload! # you'll want to implement a timeout in your production app
75
- end
72
+ # reloads the response once per second until all processing is finished
73
+ response.reload_until_finished!
76
74
 
77
75
  if response.error?
78
76
  # handle error
@@ -80,8 +78,10 @@ else
80
78
  # handle other cases
81
79
  end
82
80
  ```
81
+ *(note: the assembly method `submit!` has been deprecated and replaced with `create!`.
82
+ The submit! method remains as an alias of `create!` for backward Compatibility)*
83
83
 
84
- When the `submit!` method returns, the file has been uploaded but may not yet
84
+ When the `create!` method returns, the file has been uploaded but may not yet
85
85
  be done processing. We can use the returned object to check if processing has
86
86
  completed, or examine other attributes of the request.
87
87
 
@@ -117,6 +117,10 @@ assembly to reload its results from the API.
117
117
  ```ruby
118
118
  # reloads the response's contents from the REST API
119
119
  response.reload!
120
+
121
+ # reloads once per second until all processing is finished, up to number of
122
+ # times specified in :tries option, othewise will raise ReloadLimitReached
123
+ response.reload_until_finished! tries: 300 # default is 600
120
124
  ```
121
125
 
122
126
  In general, you use hash accessor syntax to query any direct attribute from
@@ -128,20 +132,26 @@ Transloadit HTTP API.
128
132
 
129
133
  ### 2. Uploading multiple files
130
134
 
131
- Multiple files can be given to the `submit!` method in order to upload more
135
+ Multiple files can be given to the `create!` method in order to upload more
132
136
  than one file in the same request. You can also pass a single step for the
133
137
  `steps` parameter, without having to wrap it in an Array.
134
138
 
135
139
  ```ruby
136
140
  assembly = transloadit.assembly(steps: store)
137
141
 
138
- response = assembly.submit!(
142
+ response = assembly.create!(
139
143
  open('puppies.jpg'),
140
144
  open('kittens.jpg'),
141
145
  open('ferrets.jpg')
142
146
  )
143
147
  ```
144
148
 
149
+ You can also pass an array of files to the `create!` method. Just unpack the array using the splat `*` operator.
150
+ ```ruby
151
+ files = [open('puppies.jpg'), open('kittens.jpg'), open('ferrets.jpg')]
152
+ response = assembly.create! *files
153
+ ```
154
+
145
155
  ### 3. Parallel Assembly
146
156
 
147
157
  Transloadit allows you to perform several processing steps in parallel. You
@@ -157,7 +167,7 @@ export.use [ encode, thumbs ]
157
167
 
158
168
  transloadit.assembly(
159
169
  :steps => [ encode, thumbs, export ]
160
- ).submit! open('ninja-cat.mpg')
170
+ ).create! open('ninja-cat.mpg')
161
171
  ```
162
172
 
163
173
  You can also tell a step to use the original uploaded file by passing the
@@ -166,15 +176,15 @@ Symbol `:original` instead of another step.
166
176
  Check the YARD documentation for more information on using
167
177
  [use](http://rubydoc.info/gems/transloadit/frames/Transloadit/Step#use-instance_method).
168
178
 
169
- ### 4. Using a Template
179
+ ### 4. Creating an Assembly with Templates
170
180
 
171
- Transloadit allows you to use custom [templates](http://transloadit.com/docs/templates)
181
+ Transloadit allows you to use custom [templates](https://github.com/transloadit/ruby-sdk/blob/master/README.md#8-templates)
172
182
  for recurring encoding tasks. In order to use these do the following:
173
183
 
174
184
  ```ruby
175
185
  transloadit.assembly(
176
186
  :template_id => 'YOUR_TEMPLATE_ID'
177
- ).submit! open('ninja-cat.mpg')
187
+ ).create! open('ninja-cat.mpg')
178
188
  ```
179
189
 
180
190
  You can use your steps together with this template and even use variables.
@@ -190,7 +200,7 @@ to the upload itself. You can use fields like the following:
190
200
  ```ruby
191
201
  transloadit.assembly(
192
202
  :fields => {:tag => 'ninjacats'}
193
- ).submit! open('ninja-cat.mpg')
203
+ ).create! open('ninja-cat.mpg')
194
204
  ```
195
205
 
196
206
  ### 6. Notify URL
@@ -201,24 +211,139 @@ a notify url for the assembly.
201
211
  ```ruby
202
212
  transloadit.assembly(
203
213
  :notify_url => 'http://example.com/processing_finished'
204
- ).submit! open('ninja-cat.mpg')
214
+ ).create! open('ninja-cat.mpg')
205
215
  ```
206
216
 
207
217
  Read up more on the notifications [on Transloadit's documentation page](http://transloadit.com/docs/notifications-vs-redirect-url)
208
218
 
219
+ ### 7. Other Assembly methods
220
+
221
+ Transloadit also provides methods to retrieve/replay assemblies and their notifications.
222
+
223
+ ```ruby
224
+ assembly = transloadit.assembly
225
+
226
+ # returns a list of all assemblies
227
+ assembly.list
228
+
229
+ # returns a specific assembly
230
+ assembly.get 'YOUR_ASSEMBLY_ID'
231
+
232
+ # replays a specific assembly
233
+ response = assembly.replay 'YOUR_ASSEMBLY_ID'
234
+ # should return true if assembly is replaying and false otherwise.
235
+ response.replaying?
236
+
237
+ # returns all assembly notifications
238
+ assembly.get_notifications
239
+
240
+ # replays an assembly notification
241
+ assembly.replay_notification 'YOUR_ASSEMBLY_ID'
242
+ ```
243
+
244
+ ### 8. Templates
245
+
246
+ Transloadit provides a [templates api](https://transloadit.com/docs/templates)
247
+ for recurring encoding tasks. Here's how you would create a template:
248
+
249
+ ```ruby
250
+ template = transloadit.template
251
+
252
+ # creates a new template
253
+ template.create(
254
+ :name => 'TEMPLATE_NAME',
255
+ :template => {
256
+ "steps": {
257
+ "encode": {
258
+ "use": ":original",
259
+ "robot": "/video/encode",
260
+ "result": true
261
+ }
262
+ }
263
+ }
264
+ )
265
+ ```
266
+
267
+ There are also some other methods to retrieve, update and delete a template.
268
+
269
+ ```ruby
270
+ # returns a list of all templates.
271
+ template.list
272
+
273
+ # returns a specific template.
274
+ template.get 'YOUR_TEMPLATE_ID'
275
+
276
+ # updates the template whose id is specified.
277
+ template.update(
278
+ 'YOUR_TEMPLATE_ID',
279
+ :name => 'CHANGED_TEMPLATE_NAME',
280
+ :template => {
281
+ :steps => {
282
+ :encode => {
283
+ :use => ':original',
284
+ :robot => '/video/merge'
285
+ }
286
+ }
287
+ }
288
+ )
289
+
290
+ # deletes a specific template
291
+ template.delete 'YOUR_TEMPLATE_ID'
292
+ ```
293
+
294
+ ### 9. Getting Bill reports
295
+
296
+ If you want to retrieve your transloadit account billing report for a particular month and year
297
+ you can use the `bill` method passing the required month and year like the following:
298
+
299
+ ```ruby
300
+ # returns bill report for February, 2016.
301
+ transloadit.bill(2, 2016)
302
+ ```
303
+ Not specifying the `month` or `year` would default to the current month or year.
304
+
305
+ ### 10. Rate limits
306
+
307
+ Transloadit enforces rate limits to guarantee that no customers are adversely affected by the usage
308
+ of any given customer. See [Rate Limiting](https://transloadit.com/docs/api-docs/#rate-limiting).
309
+
310
+ While creating an assembly, if a rate limit error is received, by default, 2 more attempts would be made for a succesful
311
+ response. If after these attempts the rate limit error persists, a `RateLimitReached` exception will be raised.
312
+
313
+ To change the number of attempts that will be made when creating an assembly, you may pass the `tries` option to your
314
+ assembly like so.
315
+
316
+ ```ruby
317
+ # would make one extra attempt after a failed attempt.
318
+ transloadit.assembly(:tries => 2).create! open('ninja-cat.mpg')
319
+
320
+ # Would make no attempt at all. Your request would not be sent.
321
+ transloadit.assembly(:tries => 0).create! open('ninja-cat.mpg')
322
+ ```
323
+
209
324
  ## Documentation
210
325
 
211
326
  Up-to-date YARD documentation is automatically generated. You can view the
212
327
  docs for the [released gem](http://rubydoc.info/gems/transloadit/frames) or
213
328
  for the latest [git master](http://rubydoc.info/github/transloadit/ruby-sdk/master/frames).
214
329
 
330
+ ## Examples
331
+
332
+ An small sample tutorial of using the Transloadit ruby-sdk to optimize an image, encode MP3 audio, add ID3 tags,
333
+ and more can be found [here](examples/README.md).
334
+
215
335
  ## Compatibility
216
336
 
217
- At a minimum, this gem should work on MRI 2.3.0, 2.2.0, 2.1.0, 2.0.0, 1.9.3, 1.9.2, Rubinius,
218
- and JRuby in 1.9 mode. It may also work on older ruby versions, but support for those
337
+ At a minimum, this gem should work on MRI 2.3.0, 2.2.0, 2.1.0, Rubinius,
338
+ and JRuby. It may also work on older ruby versions, but support for those
219
339
  Rubies is not guaranteed. If it doesn't work on one of the officially supported Rubies, please file a
220
340
  [bug report](https://github.com/transloadit/ruby-sdk/issues). Compatibility patches for other Rubies
221
341
  are welcome.
222
342
 
223
343
  Testing against these versions is performed automatically by
224
344
  [Travis CI](https://travis-ci.org/transloadit/ruby-sdk).
345
+
346
+ ### Ruby 1.9.x & 2.0
347
+
348
+ If you still need support for older versions of Ruby, 1.2.0 is the last version that
349
+ supports those.
@@ -0,0 +1,185 @@
1
+ # Example Usage of the Transloadit Ruby SDK
2
+
3
+ ### See an example
4
+ Navigate to an example directory (e.g. ```basic```) and then run the following, making sure to
5
+ substitute your own values for the environment variables below:
6
+ ```bash
7
+ TRANSLOADIT_KEY=<your-transloadit-key> \
8
+ TRANSLOADIT_SECRET=<your-transloadit-secret> \
9
+ S3_BUCKET=<your-s3-bucket> \
10
+ S3_ACCESS_KEY=<your-s3-access-key> \
11
+ S3_SECRET_KEY=<your-s3-secret-key> \
12
+ S3_REGION=<your-s3-region> \
13
+ main.rb
14
+ ```
15
+
16
+ ## Code Review
17
+
18
+ ### Overview
19
+
20
+ In each example we utilize a simple base class `MediaTranscoder`. This class provides us
21
+ with two methods:
22
+
23
+ ```
24
+ transloadit_client
25
+ get_status!
26
+ ```
27
+
28
+ The first method is responsible for returning us an instance of the Transloadit SDK object,
29
+ utilizing our credentials that we set in environment variables.
30
+
31
+ The second method is responsible for returning us the status of an assembly. Note that it
32
+ extends `Transloadit::Response::Assembly` to give us access to convenience methods like
33
+ `finished?`.
34
+
35
+ ### First example
36
+
37
+ In the first example that gets played, we fetch an image from the cat api, optimize it
38
+ using the Transloadit `/image/optimize` robot, and then store it in s3.
39
+
40
+ There are only two steps:
41
+ ```
42
+ optimize = transloadit_client.step('image', '/image/optimize', {
43
+ progressive: true,
44
+ use: ':original',
45
+ result: true
46
+ })
47
+ store = transloadit_client.step('store', '/s3/store', {
48
+ key: ENV.fetch('S3_ACCESS_KEY'),
49
+ secret: ENV.fetch('S3_SECRET_KEY'),
50
+ bucket: ENV.fetch('S3_BUCKET'),
51
+ bucket_region: ENV.fetch('S3_REGION'),
52
+ use: 'image'
53
+ })
54
+ ```
55
+ Again, we utilize environment variables to access our s3 credentials and pass them to
56
+ our assembly.
57
+
58
+ The job is invoked by running the following:
59
+ ```
60
+ assembly = transloadit_client.assembly(steps: [optimize, store])
61
+ assembly.submit! open(file)
62
+ ```
63
+ We pass the two steps we defined above and call `open` on the file passed in. This method
64
+ assumes the file object passed in responds to `open`.
65
+
66
+ ### Second example
67
+
68
+ In the second example, we take a non-mp3 audio file, encode it as an mp3, add ID3 tags to it,
69
+ and then store it in s3. There are many use cases for audio uploads, and adding ID3 tags
70
+ provides the necessary metadata to display artist and track information in audio players
71
+ such as iTunes.
72
+
73
+ We have the following steps:
74
+
75
+ ```
76
+ encode_mp3 = transloadit_client.step('mp3_encode', '/audio/encode', {
77
+ use: ':original',
78
+ preset: 'mp3',
79
+ ffmpeg_stack: 'v2.2.3',
80
+ result: true
81
+ })
82
+ write_metadata = transloadit_client.step('mp3', '/meta/write', {
83
+ use: 'mp3_encode',
84
+ ffmpeg_stack: 'v2.2.3',
85
+ result: true,
86
+ data_to_write: mp3_metadata
87
+ })
88
+ store = transloadit_client.step('store', '/s3/store', {
89
+ key: ENV.fetch('S3_ACCESS_KEY'),
90
+ secret: ENV.fetch('S3_SECRET_KEY'),
91
+ bucket: ENV.fetch('S3_BUCKET'),
92
+ bucket_region: ENV.fetch('S3_REGION'),
93
+ use: ['mp3']
94
+ })
95
+ ```
96
+
97
+ The first step simply uses the original file to create an mp3 version using the `audio/encode`
98
+ robot.
99
+
100
+ The second step takes the first step as input, and adds the appropriate metadata using the `meta/write`
101
+ robot. In our simple example we set the track name to the name of the file using variable
102
+ name substitution (see https://transloadit.com/docs/#assembly-variables), and set canned
103
+ values for all other ID3 fields
104
+
105
+ ```
106
+ def mp3_metadata
107
+ meta = { publisher: 'Transloadit', title: '${file.name}' }
108
+ meta[:album] = 'Transloadit Compilation'
109
+ meta[:artist] = 'Transloadit'
110
+ meta[:track] = '1/1'
111
+ meta
112
+ end
113
+ ```
114
+
115
+ Finally, we submit the assembly in the same way as the previous example:
116
+
117
+ ```
118
+ assembly = transloadit_client.assembly(steps: [encode_mp3, write_metadata, store])
119
+ assembly.submit! open(file)
120
+ ```
121
+
122
+ ### Third example
123
+
124
+ In the third example, we take a series of mp3 files and concatenate them together.
125
+ We upload the result to s3.
126
+
127
+ This example is provided to showcase advanced usage of the `use` parameter in the `audio/concat` assembly.
128
+
129
+ In our `transcode` method, note that this time we are passed an array of files.
130
+
131
+ ```
132
+ concat = transloadit_client.step('concat', '/audio/concat', {
133
+ ffmpeg_stack: 'v2.2.3',
134
+ preset: 'mp3',
135
+ use: {
136
+ steps: files.map.each_with_index do |f, i|
137
+ { name: ':original', as: "audio_#{i}", fields: "file_#{i}" }
138
+ end
139
+ },
140
+ result: true
141
+ })
142
+ ```
143
+
144
+ Taking a look at the `concat` step, we see a different usage of the `use` parameter
145
+ than we have seen in previous examples. We are effectively able to define the ordering of the
146
+ concatenation by specifying the ```name```, `as` and `fields` parameters.
147
+
148
+ In this example, we have set the name for each to `:original`, specifying that the input
149
+ at index `i` should be the input file defined at index `i`.
150
+
151
+ It is equally important to specify the `as` parameter. This simple parameter tells the assembly
152
+ the ordering.
153
+
154
+ Finally, we have the `fields` parameter. Files that get uploaded via the Ruby SDK get sent to Transloadit
155
+ through an HTTP Rest client as a multipart/form-data request. This means that each field needs a name. The Ruby SDK
156
+ automatically adds the name `file_<index>` to the outgoing request, where `<index>` is the number specified
157
+ by its position in the array.
158
+
159
+ This is why it is important to define the ordering in the `steps` array, as there is no guarantee that items
160
+ will finish uploading in the order they are sent.
161
+
162
+ With that step complete, we can finalize our store step and submit the assembly.
163
+
164
+ ```
165
+ store = transloadit_client.step('store', '/s3/store', {
166
+ key: ENV.fetch('S3_ACCESS_KEY'),
167
+ secret: ENV.fetch('S3_SECRET_KEY'),
168
+ bucket: ENV.fetch('S3_BUCKET'),
169
+ bucket_region: ENV.fetch('S3_REGION'),
170
+ use: ['concat']
171
+ })
172
+ assembly = transloadit_client.assembly(steps: [concat, store])
173
+ assembly.submit! *open_files(files)
174
+ ```
175
+
176
+ Note the final call to `submit` and usage of the splat (`*`) operator. The `submit!` method expects
177
+ one or more arguments. If you would like to pass an array to this method, you must unpack the contents of the array
178
+ or the method will treat the argument passed in as a single object, and you may have unexpected results in your
179
+ final results.
180
+
181
+ ### Conclusion
182
+
183
+ With the above examples, we have seen how we can utilize the Transloadit Ruby SDK to perform simple image optimization,
184
+ mp3 encoding and metadata writing, and audio concatenation features provided by the Transloadit service. Please visit
185
+ https://transloadit.com/docs for the full Transloadit API documentation.