shrine-transloadit 0.5.1 → 1.0.0.beta
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 +4 -4
- data/README.md +469 -329
- data/lib/shrine/plugins/transloadit.rb +167 -326
- data/shrine-transloadit.gemspec +5 -7
- metadata +19 -43
- data/lib/shrine/plugins/transloadit2.rb +0 -48
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 379b39a12a74f5b4e3e0c9336c1cc560eaa5ce78596fc55aa8990ea017d632bf
         | 
| 4 | 
            +
              data.tar.gz: '04930268d5f2c682dac35cb635fd2e0be617fc6ce1c3bd55b0ee572f771b300f'
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 0bc371cbec27b5cf8a642eedea74c372e5b1bbef48b82956635a28dd76b02eb1436870a5ba3b18671f26bc897199c77c995df16070704688fecb3d42d11b8f74
         | 
| 7 | 
            +
              data.tar.gz: 3da98b2895dd0af05e9f6aac2cc835105b754ef91e0ae0cd528b6cd7ace93a9ac82e8b7dc1ae5dc22b928d24caff89ebb3203b9a97735ac69349e97249ec89b4
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,474 +1,608 @@ | |
| 1 1 | 
             
            # Shrine::Plugins::Transloadit
         | 
| 2 2 |  | 
| 3 | 
            -
            Provides [Transloadit] integration for [Shrine].
         | 
| 3 | 
            +
            Provides [Transloadit] integration for [Shrine], using its [Ruby SDK].
         | 
| 4 4 |  | 
| 5 | 
            -
            Transloadit is a service that helps you  | 
| 5 | 
            +
            Transloadit is a service that helps you handle file uploads, resize, crop and
         | 
| 6 6 | 
             
            watermark your images, make GIFs, transcode your videos, extract thumbnails,
         | 
| 7 | 
            -
            generate audio waveforms | 
| 8 | 
            -
             | 
| 7 | 
            +
            generate audio waveforms and more.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## Contents
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * [Installation](#installation)
         | 
| 12 | 
            +
            * [Setup](#setup)
         | 
| 13 | 
            +
              - [Credentials](#credentials)
         | 
| 14 | 
            +
            * [Usage](#usge)
         | 
| 15 | 
            +
              - [Backgrounding](#backgrounding)
         | 
| 16 | 
            +
            * [Notifications](#notifications)
         | 
| 17 | 
            +
            * [Direct uploads](#direct-uploads)
         | 
| 18 | 
            +
            * [Promotion](#promotion)
         | 
| 19 | 
            +
            * [Skipping exports](#skipping-exports)
         | 
| 20 | 
            +
            * [API](#api)
         | 
| 21 | 
            +
              - [Processing & Saving](#processing-saving)
         | 
| 22 | 
            +
              - [Generating steps](#generating-steps)
         | 
| 23 | 
            +
              - [Parsing files](#parsing-files)
         | 
| 24 | 
            +
              - [Verifying signature](#verifying-signature)
         | 
| 25 | 
            +
              - [Transloadit instance](#transloadit-instance)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ## Installation
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            Put the gem in your Gemfile:
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            ```rb
         | 
| 32 | 
            +
            # Gemfile
         | 
| 33 | 
            +
            gem "shrine-transloadit", "~> 1.0"
         | 
| 34 | 
            +
            ```
         | 
| 9 35 |  | 
| 10 36 | 
             
            ## Setup
         | 
| 11 37 |  | 
| 12 | 
            -
             | 
| 13 | 
            -
            this plugin currently supports only Amazon S3 (just because there are no Shrine
         | 
| 14 | 
            -
            integrations written for other services on that list yet). You can just add
         | 
| 15 | 
            -
            shrine-transloadit to your current setup:
         | 
| 38 | 
            +
            Load the `transloadit` plugin and configure your Transloadit key and secret:
         | 
| 16 39 |  | 
| 17 40 | 
             
            ```rb
         | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 41 | 
            +
            Shrine.plugin :transloadit, auth: {
         | 
| 42 | 
            +
              key:    "YOUR_TRANSLOADIT_KEY",
         | 
| 43 | 
            +
              secret: "YOUR_TRANSLOADIT_SECRET",
         | 
| 44 | 
            +
            }
         | 
| 21 45 | 
             
            ```
         | 
| 22 46 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
            require "shrine"
         | 
| 25 | 
            -
            require "shrine/storage/s3"
         | 
| 47 | 
            +
            ### Credentials
         | 
| 26 48 |  | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
              region: "my-region",
         | 
| 30 | 
            -
              access_key_id: "abc",
         | 
| 31 | 
            -
              secret_access_key: "xyz",
         | 
| 32 | 
            -
            }
         | 
| 49 | 
            +
            You'll need to create [credentials] for the storage services you want to import
         | 
| 50 | 
            +
            from and export to. Then you need to map these credentials to Shrine storages:
         | 
| 33 51 |  | 
| 52 | 
            +
            ```rb
         | 
| 34 53 | 
             
            Shrine.storages = {
         | 
| 35 | 
            -
              cache: Shrine::Storage::S3.new(prefix: "cache", ** | 
| 36 | 
            -
              store: Shrine::Storage::S3.new( | 
| 54 | 
            +
              cache: Shrine::Storage::S3.new(prefix: "cache", **options),
         | 
| 55 | 
            +
              store: Shrine::Storage::S3.new(**options),
         | 
| 37 56 | 
             
            }
         | 
| 38 57 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
               | 
| 41 | 
            -
                 | 
| 42 | 
            -
                 | 
| 43 | 
            -
             | 
| 58 | 
            +
            Shrine.plugin :transloadit, auth: { ... },
         | 
| 59 | 
            +
              credentials: {
         | 
| 60 | 
            +
                cache: :s3_store, # use "s3_store" credentials for :cache storage
         | 
| 61 | 
            +
                store: :s3_store, # use "s3_store" credentials for :store storage
         | 
| 62 | 
            +
              }
         | 
| 44 63 | 
             
            ```
         | 
| 45 64 |  | 
| 46 | 
            -
             | 
| 47 | 
            -
            uploads to Transloadit], or just use any other `:cache` storage which provides
         | 
| 48 | 
            -
            URLs for uploaded files.
         | 
| 49 | 
            -
             | 
| 50 | 
            -
            ## How it works
         | 
| 51 | 
            -
             | 
| 52 | 
            -
            Transloadit works in a way that you create an "assembly", which contains all
         | 
| 53 | 
            -
            information about how the file(s) should be processed, from import to export.
         | 
| 54 | 
            -
            Processing itself happens asynchronously, and you can give Transloadit a URL
         | 
| 55 | 
            -
            which it will POST results to when processing finishes.
         | 
| 65 | 
            +
            ### Derivatives
         | 
| 56 66 |  | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
            a URL to the route in your app where you'd like Transloadit to POST the results
         | 
| 60 | 
            -
            of processing. Then you can call the plugin again in the route to save the
         | 
| 61 | 
            -
            results to your attachment column.
         | 
| 67 | 
            +
            The examples will assume you have the [`derivatives`][derivatives] plugin
         | 
| 68 | 
            +
            loaded:
         | 
| 62 69 |  | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 70 | 
            +
            ```rb
         | 
| 71 | 
            +
            Shrine.plugin :derivatives
         | 
| 72 | 
            +
            ```
         | 
| 65 73 |  | 
| 66 74 | 
             
            ## Usage
         | 
| 67 75 |  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 76 | 
            +
            The `transloadit` plugin provides helper methods for creating [import][import
         | 
| 77 | 
            +
            robots] and [export][export robots] steps, as well as for parsing out exported
         | 
| 78 | 
            +
            files from results.
         | 
| 71 79 |  | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 80 | 
            +
            Here is a basic example where we kick off transcoding and thumbnail extraction
         | 
| 81 | 
            +
            from an attached video, wait for assembly to complete, then save processed
         | 
| 82 | 
            +
            files as derivatives:
         | 
| 75 83 |  | 
| 76 84 | 
             
            ```rb
         | 
| 77 | 
            -
            class  | 
| 78 | 
            -
               | 
| 79 | 
            -
                 | 
| 80 | 
            -
             | 
| 85 | 
            +
            class VideoUploader < Shrine
         | 
| 86 | 
            +
              Attacher.transloadit_processor :video do
         | 
| 87 | 
            +
                import = file.transloadit_import_step
         | 
| 88 | 
            +
                encode = transloadit_step "encode", "/video/encode", use: import
         | 
| 89 | 
            +
                thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
         | 
| 90 | 
            +
                export = store.transloadit_export_step use: [encode, thumbs]
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                assembly = transloadit.assembly(steps: [import, encode, thumbs, export])
         | 
| 93 | 
            +
                assembly.create!
         | 
| 94 | 
            +
              end
         | 
| 81 95 |  | 
| 82 | 
            -
             | 
| 96 | 
            +
              Attacher.transloadit_saver :video do |response|
         | 
| 97 | 
            +
                transcoded = store.transloadit_file(response["results"]["encode"])
         | 
| 98 | 
            +
                thumbnails = store.transloadit_files(response["results"]["thumbs"])
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                merge_derivatives(transcoded: transcoded, thumbnails: thumbnails)
         | 
| 83 101 | 
             
              end
         | 
| 84 102 | 
             
            end
         | 
| 85 103 | 
             
            ```
         | 
| 104 | 
            +
            ```rb
         | 
| 105 | 
            +
            response = attacher.transloadit_process(:video)
         | 
| 106 | 
            +
            response.reload_until_finished!
         | 
| 86 107 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 108 | 
            +
            if response.error?
         | 
| 109 | 
            +
              # handle error
         | 
| 110 | 
            +
            end
         | 
| 90 111 |  | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 112 | 
            +
            attacher.transloadit_save(:video, response)
         | 
| 113 | 
            +
            attacher.derivatives #=>
         | 
| 114 | 
            +
            # {
         | 
| 115 | 
            +
            #   transcoded: #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 116 | 
            +
            #   thumbnails: [
         | 
| 117 | 
            +
            #     #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 118 | 
            +
            #     #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 119 | 
            +
            #     ...
         | 
| 120 | 
            +
            #   ]
         | 
| 121 | 
            +
            # }
         | 
| 122 | 
            +
            ```
         | 
| 96 123 |  | 
| 97 | 
            -
            ###  | 
| 124 | 
            +
            ### Backgrounding
         | 
| 98 125 |  | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 126 | 
            +
            When using [backgrounding], it's probably best to create the assembly after
         | 
| 127 | 
            +
            promotion:
         | 
| 101 128 |  | 
| 102 129 | 
             
            ```rb
         | 
| 103 | 
            -
            class  | 
| 104 | 
            -
               | 
| 130 | 
            +
            class PromoteJob
         | 
| 131 | 
            +
              def perform(record, name, file_data)
         | 
| 132 | 
            +
                attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
         | 
| 133 | 
            +
                attacher.atomic_promote
         | 
| 134 | 
            +
                attacher.transloadit_process(:video)
         | 
| 135 | 
            +
                # ...
         | 
| 136 | 
            +
              rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
            end
         | 
| 139 | 
            +
            ```
         | 
| 105 140 |  | 
| 106 | 
            -
             | 
| 107 | 
            -
                original = transloadit_file(io)
         | 
| 108 | 
            -
                medium = original.add_step("resize_500", "/image/resize", width: 500)
         | 
| 109 | 
            -
                small = original.add_step("resize_300", "/image/resize", width: 300)
         | 
| 141 | 
            +
            ## Notifications
         | 
| 110 142 |  | 
| 111 | 
            -
             | 
| 143 | 
            +
            When using [assembly notifications], the attacher data can be sent to the
         | 
| 144 | 
            +
            webhook via `:fields`:
         | 
| 112 145 |  | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 146 | 
            +
            ```rb
         | 
| 147 | 
            +
            Attacher.transloadit_processor :video do
         | 
| 148 | 
            +
              # ...
         | 
| 149 | 
            +
              assembly = transloadit.assembly(
         | 
| 150 | 
            +
                steps:      [ ... ],
         | 
| 151 | 
            +
                notify_url: "https://example.com/webhooks/transloadit",
         | 
| 152 | 
            +
                fields:     {
         | 
| 153 | 
            +
                  attacher: {
         | 
| 154 | 
            +
                    record_class: record.class,
         | 
| 155 | 
            +
                    record_id:    record.id,
         | 
| 156 | 
            +
                    name:         name,
         | 
| 157 | 
            +
                    data:         file_data,
         | 
| 158 | 
            +
                  }
         | 
| 159 | 
            +
                }
         | 
| 160 | 
            +
              )
         | 
| 161 | 
            +
              assembly.create!
         | 
| 115 162 | 
             
            end
         | 
| 116 163 | 
             
            ```
         | 
| 117 164 |  | 
| 118 | 
            -
             | 
| 165 | 
            +
            Then in the webhook handler we can load the attacher and [atomically
         | 
| 166 | 
            +
            persist][atomic_helpers] assembly results. If during processing the attachment
         | 
| 167 | 
            +
            has changed or record was deleted, we make sure we delete processed files.
         | 
| 119 168 |  | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
            format in which shrine-transloadit should save the processed files.
         | 
| 169 | 
            +
            ```rb
         | 
| 170 | 
            +
            post "/transloadit/video" do
         | 
| 171 | 
            +
              Shrine.transloadit_verify!(params) # verify transloadit signature
         | 
| 124 172 |  | 
| 125 | 
            -
             | 
| 173 | 
            +
              response = JSON.parse(params["transloadit"])
         | 
| 126 174 |  | 
| 127 | 
            -
             | 
| 175 | 
            +
              record_class, record_id, name, file_data = response["fields"]["attacher"].values
         | 
| 176 | 
            +
              record_class = Object.const_get(record_class)
         | 
| 128 177 |  | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
                thumbs = transloadit_file(io)
         | 
| 133 | 
            -
                  .add_step("thumbs", "/document/thumbs", ...)
         | 
| 134 | 
            -
                  .multiple(:list) # marks that the result of this pipeline should be saved as a list
         | 
| 178 | 
            +
              begin
         | 
| 179 | 
            +
                record   = record_class.find(record_id)
         | 
| 180 | 
            +
                attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
         | 
| 135 181 |  | 
| 136 | 
            -
                 | 
| 182 | 
            +
                attacher.transloadit_save(:video, response)
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                attacher.atomic_persist
         | 
| 185 | 
            +
              rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
         | 
| 186 | 
            +
                unless attacher
         | 
| 187 | 
            +
                  attacher = record_class.send(:"#{name}_attacher")
         | 
| 188 | 
            +
                  attacher.transloadit_save(:video, response)
         | 
| 189 | 
            +
                end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                attacher.destroy(background: true) # delete orphaned files
         | 
| 137 192 | 
             
              end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
              # return successful response for Transloadit
         | 
| 195 | 
            +
              status 200
         | 
| 138 196 | 
             
            end
         | 
| 139 197 | 
             
            ```
         | 
| 140 198 |  | 
| 141 | 
            -
             | 
| 199 | 
            +
            Note that if you have CSRF protection, make sure that you skip verifying the
         | 
| 200 | 
            +
            CSRF token for this route.
         | 
| 201 | 
            +
             | 
| 202 | 
            +
            ## Direct uploads
         | 
| 142 203 |  | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
            # [
         | 
| 146 | 
            -
            #   #<Shrine::UploadedFile ...>
         | 
| 147 | 
            -
            #   #<Shrine::UploadedFile ...>
         | 
| 148 | 
            -
            #   ...
         | 
| 149 | 
            -
            # ]
         | 
| 204 | 
            +
            Transloadit supports client side uploads via [Robodog], an [Uppy]-based
         | 
| 205 | 
            +
            JavaScript library.
         | 
| 150 206 |  | 
| 151 | 
            -
             | 
| 207 | 
            +
            If you have an HTML form, you can use Robodog's [Form API][Robodog Form] to add
         | 
| 208 | 
            +
            Transloadit's encoding capabilities to it:
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            ```js
         | 
| 211 | 
            +
            window.Robodog.form('form#myform', {
         | 
| 212 | 
            +
              params: {
         | 
| 213 | 
            +
                auth: { key: 'YOUR_TRANSLOADIT_KEY' },
         | 
| 214 | 
            +
                template_id: 'YOUR_TEMPLATE_ID',
         | 
| 215 | 
            +
              },
         | 
| 216 | 
            +
              waitForEncoding: true,
         | 
| 217 | 
            +
              // ...
         | 
| 218 | 
            +
            })
         | 
| 152 219 | 
             
            ```
         | 
| 153 220 |  | 
| 154 | 
            -
             | 
| 221 | 
            +
            With the above setup, Robodog will send the assembly results to your controller
         | 
| 222 | 
            +
            in the `transloadit` param, which we can parse out and save to our record. See
         | 
| 223 | 
            +
            the [demo app] for an example of doing this.
         | 
| 224 | 
            +
             | 
| 225 | 
            +
            ## Promotion
         | 
| 155 226 |  | 
| 156 | 
            -
            Transloadit  | 
| 157 | 
            -
             | 
| 227 | 
            +
            If you want Transloadit to also upload your cached original file to permanent
         | 
| 228 | 
            +
            storage, you can skip promotion on the Shrine side:
         | 
| 158 229 |  | 
| 159 230 | 
             
            ```rb
         | 
| 160 | 
            -
            class  | 
| 161 | 
            -
               | 
| 162 | 
            -
                 | 
| 163 | 
            -
                 | 
| 231 | 
            +
            class VideoUploader < Shrine
         | 
| 232 | 
            +
              Attacher.transloadit_processor :video do
         | 
| 233 | 
            +
                import = file.transloadit_import_step
         | 
| 234 | 
            +
                encode = transloadit_step "encode", "/video/encode", use: import
         | 
| 235 | 
            +
                thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
         | 
| 236 | 
            +
                export = store.transloadit_export_step use: [import, encode, thumbs] # include original
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                assembly = transloadit.assembly(use: [import, encode, thumbs, export])
         | 
| 239 | 
            +
                assembly.create!
         | 
| 240 | 
            +
              end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
              Attacher.transloadit_saver :video do |response|
         | 
| 243 | 
            +
                stored     = store.transloadit_file(response["results"]["import"])
         | 
| 244 | 
            +
                transcoded = store.transloadit_file(response["results"]["encode"])
         | 
| 245 | 
            +
                thumbnails = store.transloadit_files(response["results"]["thumbs"])
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                set(stored) # set promoted file
         | 
| 248 | 
            +
                merge_derivatives(transcoded: transcoded, thumbnails: thumbnails)
         | 
| 164 249 | 
             
              end
         | 
| 165 250 | 
             
            end
         | 
| 166 251 | 
             
            ```
         | 
| 252 | 
            +
            ```rb
         | 
| 253 | 
            +
            class PromoteJob
         | 
| 254 | 
            +
              def perform(record, name, file_data)
         | 
| 255 | 
            +
                attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
         | 
| 167 256 |  | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 257 | 
            +
                response = attacher.transloadit_process(:video)
         | 
| 258 | 
            +
                response.reload_until_finished!
         | 
| 170 259 |  | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 260 | 
            +
                if response.error?
         | 
| 261 | 
            +
                  # handle error
         | 
| 262 | 
            +
                end
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                original_file = attacher.file
         | 
| 265 | 
            +
                attacher.transloadit_save(:video, response)
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                attacher.atomic_persist(original_file)
         | 
| 268 | 
            +
              rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
         | 
| 269 | 
            +
                # delete orphaned processed files (backgrounding plugin is recommended)
         | 
| 270 | 
            +
                attacher.destroy(background: true) if attacher
         | 
| 271 | 
            +
              end
         | 
| 175 272 | 
             
            end
         | 
| 176 273 | 
             
            ```
         | 
| 177 274 |  | 
| 178 | 
            -
             | 
| 179 | 
            -
            CSRF token for this route.
         | 
| 180 | 
            -
             | 
| 181 | 
            -
            ### Direct uploads
         | 
| 275 | 
            +
            ## Skipping exports
         | 
| 182 276 |  | 
| 183 | 
            -
            Transloadit  | 
| 184 | 
            -
             | 
| 185 | 
            -
            client side uploads, take a look its [Transloadit plugin][uppy transloadit] for
         | 
| 186 | 
            -
            more details.
         | 
| 277 | 
            +
            If you want to use Transloadit only for processing, and prefer to store results
         | 
| 278 | 
            +
            to yourself, you can do so with help of the [shrine-url] gem.
         | 
| 187 279 |  | 
| 188 | 
            -
            ``` | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
              .use(Uppy.Tus, {})
         | 
| 196 | 
            -
              .use(Uppy.Transloadit, {
         | 
| 197 | 
            -
                waitForEncoding: true,
         | 
| 198 | 
            -
                params: {
         | 
| 199 | 
            -
                  auth: { key: 'YOUR_TRANSLOADIT_KEY' },
         | 
| 200 | 
            -
                  steps: {
         | 
| 201 | 
            -
                    // ...
         | 
| 202 | 
            -
                  }
         | 
| 203 | 
            -
                }
         | 
| 204 | 
            -
              })
         | 
| 280 | 
            +
            ```rb
         | 
| 281 | 
            +
            # Gemfile
         | 
| 282 | 
            +
            gem "shrine-url"
         | 
| 283 | 
            +
            ```
         | 
| 284 | 
            +
            ```rb
         | 
| 285 | 
            +
            # ...
         | 
| 286 | 
            +
            require "shrine/storage/url"
         | 
| 205 287 |  | 
| 206 | 
            -
             | 
| 288 | 
            +
            Shrine.storages = {
         | 
| 289 | 
            +
              # ...
         | 
| 290 | 
            +
              url: Shrine::Storage::Url.new,
         | 
| 291 | 
            +
            }
         | 
| 207 292 | 
             
            ```
         | 
| 208 293 |  | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
            which case Transloadit will return temporary URL to the processed files, which
         | 
| 213 | 
            -
            we can use as the uploaded file identifier:
         | 
| 294 | 
            +
            If you don't specify an export step, Transloadit will return processed files
         | 
| 295 | 
            +
            uploaded to Transloadit's temporary storage. You can load these results using
         | 
| 296 | 
            +
            the `:url` storage, and then upload them to your permanent storage:
         | 
| 214 297 |  | 
| 215 | 
            -
            ``` | 
| 216 | 
            -
             | 
| 217 | 
            -
               | 
| 218 | 
            -
                 | 
| 219 | 
            -
                 | 
| 220 | 
            -
                 | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
                  transloadit: result['meta'],
         | 
| 227 | 
            -
                }
         | 
| 228 | 
            -
              })
         | 
| 298 | 
            +
            ```rb
         | 
| 299 | 
            +
            class VideoUploader < Shrine
         | 
| 300 | 
            +
              Attacher.transloadit_processor :video do
         | 
| 301 | 
            +
                import = file.transloadit_import_step
         | 
| 302 | 
            +
                encode = transloadit_step "encode", "/video/encode", use: import
         | 
| 303 | 
            +
                thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
         | 
| 304 | 
            +
                # no export step
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                assembly = transloadit.assembly(steps: [import, encode, thumbs])
         | 
| 307 | 
            +
                assembly.create!
         | 
| 308 | 
            +
              end
         | 
| 229 309 |  | 
| 230 | 
            -
               | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 310 | 
            +
              Attacher.transloadit_saver :video do |response|
         | 
| 311 | 
            +
                url        = shrine_class.new(:url)
         | 
| 312 | 
            +
                transcoded = url.transloadit_file(response["results"]["encode"])
         | 
| 313 | 
            +
                thumbnails = url.transloadit_files(response["results"]["thumbs"])
         | 
| 233 314 |  | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 315 | 
            +
                # results are uploaded to Transloadit's temporary storage
         | 
| 316 | 
            +
                transcoded #=> #<Shrine::UploadedFile @storage_key=:url @id="https://tmp.transloadit.com/..." ...>
         | 
| 317 | 
            +
                thumbnails #=> [#<Shrine::UploadedFile @storage_key=:url @id="https://tmp.transloadit.com/..." ...>, ...]
         | 
| 236 318 |  | 
| 319 | 
            +
                # upload results to permanent storage
         | 
| 320 | 
            +
                add_derivatives(transcoded: transcoded, thumbnails: thumbnails)
         | 
| 321 | 
            +
              end
         | 
| 322 | 
            +
            end
         | 
| 323 | 
            +
            ```
         | 
| 237 324 | 
             
            ```rb
         | 
| 238 | 
            -
             | 
| 325 | 
            +
            response = attacher.transloadit_process(:video)
         | 
| 326 | 
            +
            response.reload_until_finished!
         | 
| 327 | 
            +
             | 
| 328 | 
            +
            if response.error?
         | 
| 329 | 
            +
              # handle error
         | 
| 330 | 
            +
            end
         | 
| 331 | 
            +
             | 
| 332 | 
            +
            attacher.transloadit_save(:video, response)
         | 
| 333 | 
            +
            attacher.derivatives #=>
         | 
| 334 | 
            +
            # {
         | 
| 335 | 
            +
            #   transcoded: #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 336 | 
            +
            #   thumbnails: [
         | 
| 337 | 
            +
            #     #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 338 | 
            +
            #     #<Shrine::UploadedFile storage_key=:store ...>,
         | 
| 339 | 
            +
            #     ...
         | 
| 340 | 
            +
            #   ]
         | 
| 341 | 
            +
            # }
         | 
| 239 342 | 
             
            ```
         | 
| 240 343 |  | 
| 344 | 
            +
            ## API
         | 
| 345 | 
            +
             | 
| 346 | 
            +
            ### Processor
         | 
| 347 | 
            +
             | 
| 348 | 
            +
            The processor is just a block registered under an identifier, which is expected
         | 
| 349 | 
            +
            to create a Transloadit assembly:
         | 
| 350 | 
            +
             | 
| 241 351 | 
             
            ```rb
         | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 352 | 
            +
            class VideoUploader < Shrine
         | 
| 353 | 
            +
              Attacher.transloadit_processor :video do
         | 
| 354 | 
            +
                # ...
         | 
| 355 | 
            +
              end
         | 
| 356 | 
            +
            end
         | 
| 244 357 | 
             
            ```
         | 
| 245 358 |  | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
            ### Templates
         | 
| 359 | 
            +
            It is executed when `Attacher#transloadit_process` is called:
         | 
| 249 360 |  | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 361 | 
            +
            ```rb
         | 
| 362 | 
            +
            attacher.transloadit_process(:video) # calls :video processor
         | 
| 363 | 
            +
            ```
         | 
| 252 364 |  | 
| 253 | 
            -
             | 
| 254 | 
            -
            and we just set the location of the imported file.
         | 
| 365 | 
            +
            Any arguments passed to the processor will be given to the block:
         | 
| 255 366 |  | 
| 256 367 | 
             
            ```rb
         | 
| 257 | 
            -
             | 
| 258 | 
            -
            {
         | 
| 259 | 
            -
              steps: {
         | 
| 260 | 
            -
                resize: {
         | 
| 261 | 
            -
                  robot: "/image/resize",
         | 
| 262 | 
            -
                  use: "import", # the "import" step will be passed in
         | 
| 263 | 
            -
                  width: 800
         | 
| 264 | 
            -
                },
         | 
| 265 | 
            -
                export: {
         | 
| 266 | 
            -
                  robot: "/s3/store",
         | 
| 267 | 
            -
                  use: "resize",
         | 
| 268 | 
            -
                  bucket: "YOUR_AWS_BUCKET",
         | 
| 269 | 
            -
                  key: "YOUR_AWS_KEY",
         | 
| 270 | 
            -
                  secret: "YOUR_AWS_SECRET",
         | 
| 271 | 
            -
                  bucket_region: "YOUR_AWS_REGION",
         | 
| 272 | 
            -
                  path: "videos/${unique_prefix}/${file.url_name}"
         | 
| 273 | 
            -
                }
         | 
| 274 | 
            -
              }
         | 
| 275 | 
            -
            }
         | 
| 368 | 
            +
            attacher.transloadit_process(:video, foo: "bar")
         | 
| 276 369 | 
             
            ```
         | 
| 277 370 | 
             
            ```rb
         | 
| 278 | 
            -
            class  | 
| 279 | 
            -
               | 
| 280 | 
            -
                 | 
| 281 | 
            -
                transloadit_assembly("my_template", steps: [import])
         | 
| 371 | 
            +
            class VideoUploader < Shrine
         | 
| 372 | 
            +
              Attacher.transloadit_processor :video do |options|
         | 
| 373 | 
            +
                options #=> { :foo => "bar" }
         | 
| 282 374 | 
             
              end
         | 
| 283 375 | 
             
            end
         | 
| 284 376 | 
             
            ```
         | 
| 285 377 |  | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
            Even though submitting a Transloadit assembly doesn't require any uploading, it
         | 
| 289 | 
            -
            still does two HTTP requests, so you might want to put them into a background
         | 
| 290 | 
            -
            job. You can configure that in the `TransloaditUploader` base uploader class:
         | 
| 378 | 
            +
            The processor block is executed in context of a `Shrine::Attacher` instance:
         | 
| 291 379 |  | 
| 292 380 | 
             
            ```rb
         | 
| 293 | 
            -
            class  | 
| 294 | 
            -
               | 
| 295 | 
            -
                 | 
| 296 | 
            -
                auth_secret: "your transloadit secret"
         | 
| 381 | 
            +
            class VideoUploader < Shrine
         | 
| 382 | 
            +
              Attacher.transloadit_processor :video do
         | 
| 383 | 
            +
                self #=> #<Shrine::Attacher>
         | 
| 297 384 |  | 
| 298 | 
            -
             | 
| 385 | 
            +
                record #=> #<Video>
         | 
| 386 | 
            +
                name   #=> :file
         | 
| 387 | 
            +
                file   #=> #<Shrine::UploadedFile>
         | 
| 388 | 
            +
              end
         | 
| 299 389 | 
             
            end
         | 
| 300 390 | 
             
            ```
         | 
| 301 | 
            -
            ```rb
         | 
| 302 | 
            -
            class TransloaditJob
         | 
| 303 | 
            -
              include Sidekiq::Worker
         | 
| 304 391 |  | 
| 305 | 
            -
             | 
| 306 | 
            -
             | 
| 392 | 
            +
            ### Saver
         | 
| 393 | 
            +
             | 
| 394 | 
            +
            The saver is just a block registered under an identifier, which is expected to
         | 
| 395 | 
            +
            save given Transloadit results into the attacher:
         | 
| 396 | 
            +
             | 
| 397 | 
            +
            ```rb
         | 
| 398 | 
            +
            class VideoUploader < Shrine
         | 
| 399 | 
            +
              Attacher.transloadit_saver :video do |results|
         | 
| 400 | 
            +
                # ...
         | 
| 307 401 | 
             
              end
         | 
| 308 402 | 
             
            end
         | 
| 309 403 | 
             
            ```
         | 
| 310 404 |  | 
| 311 | 
            -
             | 
| 405 | 
            +
            It is executed when `Attacher#transloadit_save` is called:
         | 
| 406 | 
            +
             | 
| 407 | 
            +
            ```rb
         | 
| 408 | 
            +
            attacher.transloadit_save(:video, results) # calls :video saver
         | 
| 409 | 
            +
            ```
         | 
| 312 410 |  | 
| 313 | 
            -
             | 
| 314 | 
            -
            about the status of that assembly, which the plugin saves to the cached
         | 
| 315 | 
            -
            attachment's metadata.
         | 
| 411 | 
            +
            Any arguments passed to the saver will be given to the block:
         | 
| 316 412 |  | 
| 317 413 | 
             
            ```rb
         | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 325 | 
            -
             | 
| 326 | 
            -
            #   "execution_duration" => 2.113,
         | 
| 327 | 
            -
            #   "params"             => "{\"steps\":{...}}",
         | 
| 328 | 
            -
            #   ...
         | 
| 329 | 
            -
            # }
         | 
| 414 | 
            +
            attacher.transloadit_save(:video, results, foo: "bar")
         | 
| 415 | 
            +
            ```
         | 
| 416 | 
            +
            ```rb
         | 
| 417 | 
            +
            class VideoUploader < Shrine
         | 
| 418 | 
            +
              Attacher.transloadit_saver :video do |results, options|
         | 
| 419 | 
            +
                options #=> { :foo => "bar" }
         | 
| 420 | 
            +
              end
         | 
| 421 | 
            +
            end
         | 
| 330 422 | 
             
            ```
         | 
| 331 423 |  | 
| 332 | 
            -
             | 
| 333 | 
            -
            information:
         | 
| 424 | 
            +
            The saver block is executed in context of a `Shrine::Attacher` instance:
         | 
| 334 425 |  | 
| 335 426 | 
             
            ```rb
         | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 427 | 
            +
            class VideoUploader < Shrine
         | 
| 428 | 
            +
              Attacher.transloadit_saver :video do |results|
         | 
| 429 | 
            +
                self #=> #<Shrine::Attacher>
         | 
| 430 | 
            +
             | 
| 431 | 
            +
                record #=> #<Video>
         | 
| 432 | 
            +
                name   #=> :file
         | 
| 433 | 
            +
                file   #=> #<Shrine::UploadedFile>
         | 
| 434 | 
            +
              end
         | 
| 435 | 
            +
            end
         | 
| 339 436 | 
             
            ```
         | 
| 340 437 |  | 
| 341 | 
            -
            ###  | 
| 438 | 
            +
            ### Step
         | 
| 342 439 |  | 
| 343 | 
            -
             | 
| 344 | 
            -
            metadata. When the Transloadit processing is finished and the results are saved
         | 
| 345 | 
            -
            as a Shrine attachment, this metadata will be automatically used to populate
         | 
| 346 | 
            -
            the attachment's metadata.
         | 
| 440 | 
            +
            You can generate `Transloadit::Step` objects with `Shrine.transloadit_step`:
         | 
| 347 441 |  | 
| 348 | 
            -
             | 
| 349 | 
            -
             | 
| 442 | 
            +
            ```rb
         | 
| 443 | 
            +
            Shrine.transloadit_step "my_name", "/my/robot", **options
         | 
| 444 | 
            +
            #=> #<Transloadit::Step name="my_name", robot="/my/robot", options={...}>
         | 
| 445 | 
            +
            ```
         | 
| 446 | 
            +
             | 
| 447 | 
            +
            This method adds the ability to pass another `Transloadit::Step` object as the
         | 
| 448 | 
            +
            `:use` parameter:
         | 
| 350 449 |  | 
| 351 450 | 
             
            ```rb
         | 
| 352 | 
            -
             | 
| 353 | 
            -
             | 
| 354 | 
            -
             | 
| 355 | 
            -
            #   "date_recorded"         => "2013/09/04 08:03:39",
         | 
| 356 | 
            -
            #   "date_file_created"     => "2013/09/04 12:03:39 GMT",
         | 
| 357 | 
            -
            #   "date_file_modified"    => "2016/07/11 02:27:11 GMT",
         | 
| 358 | 
            -
            #   "aspect_ratio"          => "1.504",
         | 
| 359 | 
            -
            #   "city"                  => "Decatur",
         | 
| 360 | 
            -
            #   "state"                 => "Georgia",
         | 
| 361 | 
            -
            #   "country"               => "United States",
         | 
| 362 | 
            -
            #   "latitude"              => 33.77519301,
         | 
| 363 | 
            -
            #   "longitude"             => -84.295608,
         | 
| 364 | 
            -
            #   "orientation"           => "Horizontal (normal)",
         | 
| 365 | 
            -
            #   "colorspace"            => "RGB",
         | 
| 366 | 
            -
            #   "average_color"         => "#8b8688",
         | 
| 367 | 
            -
            #   ...
         | 
| 368 | 
            -
            # }
         | 
| 451 | 
            +
            step_one = Shrine.transloadit_step "one", "/robot/one"
         | 
| 452 | 
            +
            step_two = Shrine.transloadit_step "two", "/robot/two", use: step_one
         | 
| 453 | 
            +
            step_two.options[:use] #=> ["one"]
         | 
| 369 454 | 
             
            ```
         | 
| 370 455 |  | 
| 371 | 
            -
            ### Import  | 
| 456 | 
            +
            ### Import step
         | 
| 372 457 |  | 
| 373 | 
            -
             | 
| 374 | 
            -
             | 
| 458 | 
            +
            The `Shrine::UploadedFile#transloadit_import_step` method generates an import
         | 
| 459 | 
            +
            step for the uploaded file:
         | 
| 375 460 |  | 
| 376 461 | 
             
            ```rb
         | 
| 377 | 
            -
             | 
| 462 | 
            +
            file = Shrine.upload(io, :store)
         | 
| 463 | 
            +
            file.storage #=> #<Shrine::Storage::S3>
         | 
| 464 | 
            +
            file.id      #=> "foo"
         | 
| 378 465 |  | 
| 379 | 
            -
             | 
| 466 | 
            +
            step = file.transloadit_import_step
         | 
| 380 467 |  | 
| 381 | 
            -
             | 
| 382 | 
            -
             | 
| 468 | 
            +
            step       #=> #<Transloadit::Step ...>
         | 
| 469 | 
            +
            step.name  #=> "import"
         | 
| 470 | 
            +
            step.robot #=> "/s3/import"
         | 
| 471 | 
            +
             | 
| 472 | 
            +
            step.options[:path]        #=> "foo"
         | 
| 473 | 
            +
            step.options[:credentials] #=> :s3_store (inferred from the plugin setting)
         | 
| 383 474 | 
             
            ```
         | 
| 384 475 |  | 
| 476 | 
            +
            You can change the default step name:
         | 
| 477 | 
            +
             | 
| 385 478 | 
             
            ```rb
         | 
| 386 | 
            -
             | 
| 479 | 
            +
            step = file.transloadit_import_step("my_import")
         | 
| 480 | 
            +
            step.name #=> "my_import"
         | 
| 481 | 
            +
            ```
         | 
| 387 482 |  | 
| 388 | 
            -
             | 
| 483 | 
            +
            You can also pass step options:
         | 
| 389 484 |  | 
| 390 | 
            -
             | 
| 391 | 
            -
             | 
| 392 | 
            -
             | 
| 393 | 
            -
            })
         | 
| 485 | 
            +
            ```rb
         | 
| 486 | 
            +
            step = file.transloadit_import_step(ignore_errors: ["meta"])
         | 
| 487 | 
            +
            step.options[:ignore_errors] #=> ["meta"]
         | 
| 394 488 | 
             
            ```
         | 
| 395 489 |  | 
| 396 | 
            -
             | 
| 397 | 
            -
            expanded forms.
         | 
| 490 | 
            +
            The following import robots are currently supported:
         | 
| 398 491 |  | 
| 399 | 
            -
             | 
| 492 | 
            +
            | Robot          | Description                                                |
         | 
| 493 | 
            +
            | :-----------   | :----------                                                |
         | 
| 494 | 
            +
            | `/s3/import`   | activated for `Shrine::Storage::S3`                        |
         | 
| 495 | 
            +
            | `/http/import` | activated for any other storage which returns HTTP(S) URLs |
         | 
| 496 | 
            +
            | `/ftp/import`  | activated for any other storage which returns FTP URLs     |
         | 
| 400 497 |  | 
| 401 | 
            -
             | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 498 | 
            +
            ### Export step
         | 
| 499 | 
            +
             | 
| 500 | 
            +
            The `Shrine#transloadit_export_step` method generates an export step for the underlying
         | 
| 501 | 
            +
            storage:
         | 
| 404 502 |  | 
| 405 503 | 
             
            ```rb
         | 
| 406 | 
            -
             | 
| 407 | 
            -
             | 
| 408 | 
            -
             | 
| 409 | 
            -
             | 
| 410 | 
            -
             | 
| 411 | 
            -
             | 
| 412 | 
            -
               | 
| 413 | 
            -
             | 
| 504 | 
            +
            uploader = Shrine.new(:store)
         | 
| 505 | 
            +
            uploader.storage #=> #<Shrine::Storage::S3>
         | 
| 506 | 
            +
             | 
| 507 | 
            +
            step = uploader.transloadit_export_step
         | 
| 508 | 
            +
             | 
| 509 | 
            +
            step       #=> #<Transloadit::Step ...>
         | 
| 510 | 
            +
            step.name  #=> "export"
         | 
| 511 | 
            +
            step.robot #=> "/s3/store"
         | 
| 512 | 
            +
             | 
| 513 | 
            +
            step.options[:credentials] #=> :s3_store (inferred from the plugin setting)
         | 
| 414 514 | 
             
            ```
         | 
| 415 515 |  | 
| 416 | 
            -
             | 
| 516 | 
            +
            You can change the default step name:
         | 
| 417 517 |  | 
| 418 | 
            -
             | 
| 419 | 
            -
             | 
| 420 | 
            -
             | 
| 518 | 
            +
            ```rb
         | 
| 519 | 
            +
            step = uploader.transloadit_export_step("my_export")
         | 
| 520 | 
            +
            step.name #=> "my_export"
         | 
| 521 | 
            +
            ```
         | 
| 522 | 
            +
             | 
| 523 | 
            +
            You can also pass step options:
         | 
| 421 524 |  | 
| 422 525 | 
             
            ```rb
         | 
| 423 | 
            -
             | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 526 | 
            +
            step = file.transloadit_export_step(acl: "public-read")
         | 
| 527 | 
            +
            step.options[:acl] #=> "public-read"
         | 
| 528 | 
            +
            ```
         | 
| 426 529 |  | 
| 427 | 
            -
             | 
| 428 | 
            -
                  notify_url = "https://myapp.com/webhooks/transloadit"
         | 
| 429 | 
            -
                else
         | 
| 430 | 
            -
                  # In development we cannot receive webhooks, because Transloadit as an
         | 
| 431 | 
            -
                  # external service cannot reach our localhost.
         | 
| 432 | 
            -
                end
         | 
| 530 | 
            +
            The following export robots are currently supported:
         | 
| 433 531 |  | 
| 434 | 
            -
             | 
| 435 | 
            -
             | 
| 436 | 
            -
             | 
| 532 | 
            +
            | Robot            | Description                                                       |
         | 
| 533 | 
            +
            | :----            | :----------                                                       |
         | 
| 534 | 
            +
            | `/s3/store`      | activated for `Shrine::Storage::S3`                               |
         | 
| 535 | 
            +
            | `/google/store`  | activated for [`Shrine::Storage::GoogleCloudStorage`][shrine-gcs] |
         | 
| 536 | 
            +
            | `/youtube/store` | activated for [`Shrine::Storage::YouTube`][shrine-youtube]        |
         | 
| 537 | 
            +
             | 
| 538 | 
            +
            ### File
         | 
| 539 | 
            +
             | 
| 540 | 
            +
            The `Shrine#transloadit_file` method will convert a Transloadit result hash
         | 
| 541 | 
            +
            into a `Shrine::UploadedFile` object:
         | 
| 542 | 
            +
             | 
| 543 | 
            +
            ```rb
         | 
| 544 | 
            +
            uploader = Shrine.new(:store)
         | 
| 545 | 
            +
            uploader.storage #=> #<Shrine::Storage::S3>
         | 
| 546 | 
            +
             | 
| 547 | 
            +
            file = uploader.transloadit_file(
         | 
| 548 | 
            +
              "url" => "https://my-bucket.s3.amazonaws.com/foo",
         | 
| 549 | 
            +
              # ...
         | 
| 550 | 
            +
            )
         | 
| 551 | 
            +
             | 
| 552 | 
            +
            file.storage #=> #<Shrine::Storage::S3>
         | 
| 553 | 
            +
            file.id      #=> "foo"
         | 
| 437 554 | 
             
            ```
         | 
| 438 555 |  | 
| 556 | 
            +
            It will include basic metadata:
         | 
| 557 | 
            +
             | 
| 439 558 | 
             
            ```rb
         | 
| 440 | 
            -
             | 
| 441 | 
            -
               | 
| 559 | 
            +
            file = uploader.transloadit_file(
         | 
| 560 | 
            +
              # ...
         | 
| 561 | 
            +
              "name" => "matrix.mp4",
         | 
| 562 | 
            +
              "size" => 44198,
         | 
| 563 | 
            +
              "mime" => "video/mp4",
         | 
| 564 | 
            +
            )
         | 
| 565 | 
            +
             | 
| 566 | 
            +
            file.original_filename #=> "matrix.mp4"
         | 
| 567 | 
            +
            file.size              #=> 44198
         | 
| 568 | 
            +
            file.mime_type         #=> "video/mp4"
         | 
| 569 | 
            +
            ```
         | 
| 442 570 |  | 
| 443 | 
            -
             | 
| 444 | 
            -
                attacher = TransloaditUploader::Attacher.transloadit_process(data)
         | 
| 571 | 
            +
            It will also merge any custom metadata:
         | 
| 445 572 |  | 
| 446 | 
            -
             | 
| 447 | 
            -
             | 
| 448 | 
            -
             | 
| 449 | 
            -
             | 
| 450 | 
            -
             | 
| 451 | 
            -
             | 
| 452 | 
            -
             | 
| 453 | 
            -
            end
         | 
| 573 | 
            +
            ```rb
         | 
| 574 | 
            +
            file = uploader.transloadit_file(
         | 
| 575 | 
            +
              # ...
         | 
| 576 | 
            +
              "meta" => { "duration" => 9000, ... },
         | 
| 577 | 
            +
            )
         | 
| 578 | 
            +
             | 
| 579 | 
            +
            file["duration"] #=> 9000
         | 
| 454 580 | 
             
            ```
         | 
| 455 581 |  | 
| 456 | 
            -
             | 
| 582 | 
            +
            Currently only `Shrine::Stroage::S3` is supported. However, you can still
         | 
| 583 | 
            +
            handle other remote files using [`Shrine::Storage::Url`][shrine-url]:
         | 
| 457 584 |  | 
| 458 | 
            -
             | 
| 459 | 
            -
             | 
| 585 | 
            +
            ```rb
         | 
| 586 | 
            +
            Shrine.storages => {
         | 
| 587 | 
            +
              # ...
         | 
| 588 | 
            +
              url: Shrine::Storage::Url.new,
         | 
| 589 | 
            +
            }
         | 
| 590 | 
            +
            ```
         | 
| 591 | 
            +
            ```rb
         | 
| 592 | 
            +
            uploader = Shrine.new(:url)
         | 
| 593 | 
            +
            uploader #=> #<Shrine::Storage::Url>
         | 
| 460 594 |  | 
| 461 | 
            -
             | 
| 462 | 
            -
             | 
| 463 | 
            -
             | 
| 464 | 
            -
             | 
| 465 | 
            -
             | 
| 466 | 
            -
             | 
| 467 | 
            -
            S3_ACCESS_KEY_ID="..."
         | 
| 468 | 
            -
            S3_SECRET_ACCESS_KEY="..."
         | 
| 595 | 
            +
            file = uploader.transloadit_file(
         | 
| 596 | 
            +
              "url" => "https://example.com/foo",
         | 
| 597 | 
            +
              # ...
         | 
| 598 | 
            +
            )
         | 
| 599 | 
            +
             | 
| 600 | 
            +
            file.id #=> "https://example.com/foo"
         | 
| 469 601 | 
             
            ```
         | 
| 470 602 |  | 
| 471 | 
            -
             | 
| 603 | 
            +
            ## Contributing
         | 
| 604 | 
            +
             | 
| 605 | 
            +
            Tests are run with:
         | 
| 472 606 |  | 
| 473 607 | 
             
            ```sh
         | 
| 474 608 | 
             
            $ bundle exec rake test
         | 
| @@ -480,12 +614,18 @@ $ bundle exec rake test | |
| 480 614 |  | 
| 481 615 | 
             
            [Shrine]: https://github.com/shrinerb/shrine
         | 
| 482 616 | 
             
            [Transloadit]: https://transloadit.com/
         | 
| 483 | 
            -
            [ | 
| 484 | 
            -
            [ | 
| 485 | 
            -
            [ | 
| 486 | 
            -
            [ | 
| 487 | 
            -
            [ | 
| 488 | 
            -
            [ | 
| 489 | 
            -
            [ | 
| 490 | 
            -
            [ | 
| 617 | 
            +
            [Ruby SDK]: https://github.com/transloadit/ruby-sdk
         | 
| 618 | 
            +
            [credentials]: https://transloadit.com/docs/#16-template-credentials
         | 
| 619 | 
            +
            [import robots]: https://transloadit.com/docs/transcoding/#overview-service-file-importing
         | 
| 620 | 
            +
            [export robots]: https://transloadit.com/docs/transcoding/#overview-service-file-exporting
         | 
| 621 | 
            +
            [derivatives]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/derivatives.md#readme
         | 
| 622 | 
            +
            [assembly notifications]: https://transloadit.com/docs/#24-assembly-notifications
         | 
| 623 | 
            +
            [backgrounding]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/backgrounding.md#readme
         | 
| 624 | 
            +
            [shrine-url]: https://github.com/shrinerb/shrine-url
         | 
| 625 | 
            +
            [Robodog]: https://uppy.io/docs/robodog/
         | 
| 626 | 
            +
            [Robodog Form]: https://uppy.io/docs/robodog/form/
         | 
| 627 | 
            +
            [Uppy]: https://uppy.io/
         | 
| 628 | 
            +
            [atomic_helpers]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/atomic_helpers.md#readme
         | 
| 629 | 
            +
            [shrine-gcs]: https://github.com/renchap/shrine-google_cloud_storage
         | 
| 630 | 
            +
            [shrine-youtube]: https://github.com/thedyrt/shrine-storage-you_tube
         | 
| 491 631 | 
             
            [shrine-url]: https://github.com/shrinerb/shrine-url
         |