shrine-transloadit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9ad060395c4432e137702840eba7f23eef980b5
4
+ data.tar.gz: 983a7aaf98794573d4f946fe14d0014162b02bfd
5
+ SHA512:
6
+ metadata.gz: 48003055afa7b725f0f42213daf2dedb6ecf91d03f8c5805921b0ff57953202aa0a8463300a40246cb1b0984eda816972cd8a0af2b99676188ac62bd18e010c0
7
+ data.tar.gz: a4aec56c9856366f4d8fb87c00ce6d6ff8f91750033ed6c0aba48b241533358c6bc5af7b4930f7bda463ebf06ff35322de5fc948d229597b8e855808439d4bdc
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Janko Marohnić
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,345 @@
1
+ # Shrine::Plugins::Transloadit
2
+
3
+ Provides [Transloadit] integration for [Shrine].
4
+
5
+ Transloadit offers advanced file processing for all sorts of media, including
6
+ images, videos, audio, and documents, along with importing from and exporting
7
+ to various file storage services.
8
+
9
+ ## Setup
10
+
11
+ While Transloadit is able to export processed files to [many storage
12
+ services], this plugin currently supports only Amazon S3 (just because there
13
+ are no Shrine integrations written for other services on that list yet).
14
+
15
+ ```rb
16
+ gem "shrine-transloadit"
17
+ gem "aws-sdk"
18
+ ```
19
+
20
+ ```rb
21
+ require "shrine"
22
+ require "shrine/storage/s3"
23
+
24
+ s3_options = {
25
+ access_key_id: "xyz",
26
+ secret_access_key: "abc",
27
+ region: "my-region",
28
+ bucket: "my-app",
29
+ }
30
+
31
+ Shrine.storages = {
32
+ cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
33
+ store: Shrine::Storage::S3.new(prefix: "store", **s3_options),
34
+ }
35
+
36
+ Shrine.plugin :transloadit,
37
+ auth_key: "your transloadit key",
38
+ auth_secret: "your transloadit secret"
39
+ ```
40
+ ```rb
41
+ post "/webhooks/transloadit" do
42
+ Shrine::Attacher.transloadit_save(params)
43
+ end
44
+ ```
45
+
46
+ ## How it works
47
+
48
+ Transloadit works in a way that you create an "assembly", which contains all
49
+ information about how the file(s) should be processed, from import to export.
50
+ Processing itself happens asynchronously, and you can give Transloadit a URL
51
+ which it will POST results to when processing finishes.
52
+
53
+ This plugin allows you to easily implement this webhook flow. You can intercept
54
+ promoting, and submit a Transloadit assembly using the cached file, along with
55
+ a URL to the route in your app where you'd like Transloadit to POST the results
56
+ of processing. Then you can call the plugin again in the route to save the
57
+ results to your attachment column.
58
+
59
+ ## Usage
60
+
61
+ Transloadit assemblies are built inside `#transloadit_process` method in your
62
+ uploader, and you can use some convenient helper methods which the plugin
63
+ provides.
64
+
65
+ ```rb
66
+ class MyUploader < Shrine
67
+ def transloadit_process(io, context)
68
+ resized = transloadit_file(io)
69
+ .add_step("resize", "/image/resize", width: 800)
70
+
71
+ transloadit_assembly(resized, context: context)
72
+ end
73
+ end
74
+ ```
75
+
76
+ These helper methods just provide a higher-level interface over the
77
+ [transloadit gem], which you might want look at to get a better understanding
78
+ of how building assemblies works.
79
+
80
+ In short, in Transloadit every action, be it import, processing, or export, is
81
+ a "step". Each step is defined by its [robot and arguments], and needs to have
82
+ a *unique name*. Transloadit allows you to define the entire processing flow
83
+ (which can result in multiple files) as a collection of steps, which is called
84
+ an "assembly". Once the assembly is built it can be submitted to Transloadit.
85
+
86
+ ### Versions
87
+
88
+ With Transloadit you can create multiple files in a single assembly, and this
89
+ plugin allows you to leverage that in form of a hash of versions.
90
+
91
+ ```rb
92
+ class MyUploader < Shrine
93
+ plugin :versions
94
+
95
+ def transloadit_process(io, context)
96
+ original = transloadit_file(io)
97
+ medium = original.add_step("resize_500", "/image/resize", width: 500)
98
+ small = original.add_step("resize_300", "/image/resize", width: 300)
99
+
100
+ files = {original: original, medium: medium, small: small}
101
+
102
+ transloadit_assembly(files, context: context)
103
+ end
104
+ end
105
+ ```
106
+
107
+ ### Webhooks
108
+
109
+ Transloadit performs its processing asynchronously, and you can provide a URL
110
+ where you want Transloadit to POST results of processing once it's finished.
111
+
112
+ ```rb
113
+ class MyUploader < Shrine
114
+ def transloadit_process(io, context)
115
+ # ...
116
+
117
+ transloadit_assembly(files, notify_url: "http://myapp.com/webhooks/transloadit")
118
+ end
119
+ end
120
+ ```
121
+
122
+ Then in your `POST /webhooks/transloadit` route you can call the plugin to
123
+ automatically save the results to the attachment column in Shrine's format.
124
+
125
+ ```rb
126
+ post "/webhooks/transloadit" do
127
+ Shrine::Attacher.transloadit_save(params)
128
+ end
129
+ ```
130
+
131
+ ### Templates
132
+
133
+ Transloadit recommends using [templates], since they allow you to replay failed
134
+ assemblies, and also allow you not to expose credentials in your HTML.
135
+
136
+ Here is an example where the whole processing is defined inside a template,
137
+ and we just set the location of the imported file.
138
+
139
+ ```rb
140
+ # Your saved template
141
+ {
142
+ steps: {
143
+ import: {
144
+ robot: "/http/import",
145
+ url: "..."
146
+ },
147
+ resize: {
148
+ robot: "/image/resize",
149
+ use: "import",
150
+ width: 800
151
+ }
152
+ }
153
+ }
154
+ ```
155
+ ```rb
156
+ class MyUploader < Shrine
157
+ def transloadit_process(io, context)
158
+ transloadit_assembly("my_template", steps: {import: {url: io.url}})
159
+ end
160
+ end
161
+ ```
162
+
163
+ ### Backgrounding
164
+
165
+ Even though submitting a Transloadit assembly doesn't require any uploading, it
166
+ still does two HTTP requests, so you might want to put it into a backgrond job.
167
+ This plugin naturally hooks onto Shrine's backgrounding plugin:
168
+
169
+ ```rb
170
+ Shrine::Attacher.promote { |data| TransloaditJob.perform_async(data) }
171
+ ```
172
+ ```rb
173
+ class TransloaditJob
174
+ include Sidekiq::Worker
175
+
176
+ def perform(data)
177
+ Shrine::Attacher.transloadit_process(data)
178
+ end
179
+ end
180
+ ```
181
+
182
+ ### Tracking progress
183
+
184
+ When an assembly is submitted, Transloadit returns a lot of useful information
185
+ about the status of that assembly, which the plugin saves to the cached
186
+ attachment's metadata.
187
+
188
+ ```rb
189
+ response = photo.image.transloadit_response
190
+ response.body #=>
191
+ # {
192
+ # "ok" => "ASSEMBLY_EXECUTING",
193
+ # "message" => "The assembly is currently being executed.",
194
+ # "assembly_id" => "83d07d10414011e68cc8c5df79919836",
195
+ # "assembly_url" => "http://api2.janani.transloadit.com/assemblies/83d07d10414011e68cc8c5df79919836",
196
+ # "execution_start" => "2016/07/03 17:06:42 GMT",
197
+ # "execution_duration" => 2.113,
198
+ # "params" => "{\"steps\":{...}}",
199
+ # ...
200
+ # }
201
+ ```
202
+
203
+ At an point during the execution of the assembly you can refresh this
204
+ information:
205
+
206
+ ```rb
207
+ response.finished? #=> false
208
+ response.reload!
209
+ response.finished? #=> true
210
+ ```
211
+
212
+ ### Import & Export
213
+
214
+ Every `TransloaditFile` needs to have an import and an export step. This plugin
215
+ automatically generates those steps for you:
216
+
217
+ ```rb
218
+ transloadit_file(io)
219
+
220
+ # is equivalent to
221
+
222
+ file = transloadit_file
223
+ file.add_step(transloadit_import_step("import", io))
224
+ ```
225
+
226
+ ```rb
227
+ transloadit_assembly({original: original, thumb: thumb})
228
+
229
+ # is equivalent to
230
+
231
+ transloadit_assembly({
232
+ original: original.add_step(transloadit_export_step("export_original")),
233
+ thumb: thumb.add_step(transloadit_export_step("export_thumb")),
234
+ })
235
+ ```
236
+
237
+ If you want/need to generate these steps yourself, you can just use the
238
+ expanded forms.
239
+
240
+ ### Transloadit gem
241
+
242
+ If you want to have complete control over how steps are generated, you can just
243
+ use the [transloadit gem] directly. This plugin doesn't care how you generate
244
+ your steps, it only requires you to return an instance of
245
+ `Transloadit::Assembly`.
246
+
247
+ ```rb
248
+ class MyUploader < Shrine
249
+ def transloadit_process(io, context)
250
+ # build options
251
+ transloadit #=> #<Transloadit>
252
+ transloadit.assembly(options)
253
+ end
254
+ end
255
+ ```
256
+
257
+ The import/export helper methods simply generate a `Transloadit::Step` object,
258
+ and you can pass additional options:
259
+
260
+ ```rb
261
+ class MyUploader < Shrinee
262
+ def transloadit_process(io, context)
263
+ transloadit_import_step("import", io) #=> #<Transloadit::Step>
264
+ transloadit_export_step("export", path: "mypath") #=> #<Transloadit::Step>
265
+ end
266
+ end
267
+ ```
268
+
269
+ The `#add_step` method for `TransloaditFile` is just a convenient way to add
270
+ steps where `:use` is automatically set to previous step.
271
+
272
+ ### Testing
273
+
274
+ In development or test environment you cannot use webhooks, because Transloadit
275
+ as an external service cannot access your localhost. In this case you can just
276
+ do polling:
277
+
278
+ ```rb
279
+ class MyUploader < Shrine
280
+ def transloadit_process(io, context)
281
+ # ...
282
+
283
+ if ENV["RACK_ENV"] == "production"
284
+ notify_url = "https://myapp.com/webhooks/transloadit"
285
+ else
286
+ # In development we cannot receive webhooks, because Transloadit as an
287
+ # external service cannot reach our localhost.
288
+ end
289
+
290
+ transloadit_assembly(files, context: context, notify_url: notify_url)
291
+ end
292
+ end
293
+ ```
294
+
295
+ ```rb
296
+ class TransloaditJob
297
+ include Sidekiq::Worker
298
+
299
+ def perform(data)
300
+ attacher = Shrine::Attacher.transloadit_process(data)
301
+
302
+ # Webhooks won't work in development, so we can just use polling.
303
+ unless ENV["RACK_ENV"] == "production"
304
+ response = attacher.get.transloadit_response
305
+ until response.finished?
306
+ sleep 1
307
+ response.reload!
308
+ end
309
+ attacher.transloadit_save(response.body)
310
+ end
311
+ end
312
+ end
313
+ ```
314
+
315
+ ## Contributing
316
+
317
+ Before you can run tests, you need to first create an `.env` file in the
318
+ project root containing your Transloadit and Amazon S3 credentials:
319
+
320
+ ```sh
321
+ # .env
322
+ TRANSLOADIT_AUTH_KEY="..."
323
+ TRANSLOADIT_AUTH_SECRET="..."
324
+ S3_BUCKET="..."
325
+ S3_REGION="..."
326
+ S3_ACCESS_KEY_ID="..."
327
+ S3_SECRET_ACCESS_KEY="..."
328
+ ```
329
+
330
+ Afterwards you can run the tests:
331
+
332
+ ```sh
333
+ $ bundle exec rake test
334
+ ```
335
+
336
+ ## License
337
+
338
+ [MIT](LICENSE.txt)
339
+
340
+ [Shrine]: https://github.com/janko-m/shrine
341
+ [Transloadit]: https://transloadit.com/
342
+ [many storage services]: https://transloadit.com/docs/conversion-robots/#file-export-robots
343
+ [transloadit gem]: https://github.com/transloadit/ruby-sdk
344
+ [robot and arguments]: https://transloadit.com/docs/conversion-robots/
345
+ [templates]: https://transloadit.com/docs/#templates
@@ -0,0 +1,267 @@
1
+ require "transloadit"
2
+ require "uri"
3
+ require "json"
4
+ require "openssl"
5
+
6
+ class Shrine
7
+ module Plugins
8
+ module Transloadit
9
+ def self.configure(uploader, opts = {})
10
+ uploader.opts[:transloadit_auth_key] = opts.fetch(:auth_key, uploader.opts[:transloadit_auth_key])
11
+ uploader.opts[:transloadit_auth_secret] = opts.fetch(:auth_secret, uploader.opts[:transloadit_auth_secret])
12
+
13
+ raise Error, "The :auth_key is required for transloadit plugin" if uploader.opts[:transloadit_auth_key].nil?
14
+ raise Error, "The :auth_secret is required for transloadit plugin" if uploader.opts[:transloadit_auth_secret].nil?
15
+
16
+ uploader.opts[:backgrounding_promote] ||= proc { transloadit_process }
17
+ end
18
+
19
+ def self.load_dependencies(uploader, opts = {})
20
+ uploader.plugin :backgrounding
21
+ end
22
+
23
+ module AttacherClassMethods
24
+ def transloadit_process(data)
25
+ attacher = self.load(data)
26
+ cached_file = attacher.uploaded_file(data["attachment"])
27
+ attacher.transloadit_process(cached_file)
28
+ attacher
29
+ end
30
+
31
+ def transloadit_save(params)
32
+ params["transloadit"] = params["transloadit"].to_json if params["transloadit"].is_a?(Hash)
33
+ check_transloadit_signature!(params)
34
+ response = JSON.parse(params["transloadit"])
35
+ data = response["fields"]["attacher"]
36
+ attacher = self.load(data)
37
+ cached_file = attacher.uploaded_file(data["attachment"])
38
+ return if cached_file != attacher.get
39
+ attacher.transloadit_save(response)
40
+ attacher
41
+ end
42
+
43
+ def check_transloadit_signature!(params)
44
+ sent_signature = params["signature"]
45
+ payload = params["transloadit"]
46
+ algorithm = OpenSSL::Digest.new('sha1')
47
+ secret = shrine_class.opts[:transloadit_auth_secret]
48
+ calculated_signature = OpenSSL::HMAC.hexdigest(algorithm, secret, payload)
49
+ raise Error, "Transloadit signature that was sent doesn't match the calculated signature" if calculated_signature != sent_signature
50
+ end
51
+ end
52
+
53
+ module AttacherMethods
54
+ def transloadit_process(cached_file = get)
55
+ assembly = store.transloadit_process(cached_file, context)
56
+ assembly.options[:fields] ||= {}
57
+ assembly.options[:fields]["attacher"] = self.dump.merge("attachment" => cached_file.to_json)
58
+ response = assembly.submit!
59
+ raise Error, "#{response["error"]}: #{response["message"]}" if response["error"]
60
+ cached_file.metadata["transloadit_response"] = response.body.to_json
61
+ swap(cached_file)
62
+ end
63
+
64
+ def transloadit_save(response)
65
+ if versions = response["fields"]["versions"]
66
+ stored_file = versions.inject({}) do |hash, (name, key)|
67
+ result = response["results"].fetch(key)[0]
68
+ uploaded_file = store.transloadit_uploaded_file(result)
69
+ hash.update(name => uploaded_file)
70
+ end
71
+ else
72
+ result = response["results"].values.last[0]
73
+ stored_file = store.transloadit_uploaded_file(result)
74
+ end
75
+
76
+ update(stored_file)
77
+ end
78
+ end
79
+
80
+ module ClassMethods
81
+ def transloadit
82
+ ::Transloadit.new(
83
+ key: opts[:transloadit_auth_key],
84
+ secret: opts[:transloadit_auth_secret],
85
+ )
86
+ end
87
+ end
88
+
89
+ module InstanceMethods
90
+ def transloadit_uploaded_file(result)
91
+ case url = result.fetch("url")
92
+ when /amazonaws\.com/
93
+ raise Error, "Cannot save a processed file which wasn't exported: #{url.inspect}" if url.include?("tmp.transloadit.com")
94
+ path = URI(url).path
95
+ id = path.match(/^\/#{storage.prefix}/).post_match
96
+ else
97
+ raise Error, "The transloadit Shrine plugin doesn't support storage identified by #{url.inspect}"
98
+ end
99
+
100
+ self.class::UploadedFile.new(
101
+ "id" => id,
102
+ "storage" => storage_key,
103
+ "metadata" => {
104
+ "filename" => result.fetch("name"),
105
+ "size" => result.fetch("size"),
106
+ "mime_type" => result.fetch("mime"),
107
+ "width" => (result["meta"] && result["meta"]["width"]),
108
+ "height" => (result["meta"] && result["meta"]["height"]),
109
+ "transloadit" => result["meta"],
110
+ }
111
+ )
112
+ end
113
+
114
+ def transloadit_import_step(name, io, **step_options)
115
+ uri = URI.parse(io.url)
116
+
117
+ if defined?(Storage::S3) && io.storage.is_a?(Storage::S3)
118
+ step = transloadit.step(name, "/s3/import",
119
+ key: io.storage.s3.client.config.access_key_id,
120
+ secret: io.storage.s3.client.config.secret_access_key,
121
+ bucket: io.storage.bucket.name,
122
+ bucket_region: io.storage.s3.client.config.region,
123
+ path: [*io.storage.prefix, io.id].join("/"),
124
+ )
125
+ elsif uri.scheme == "http" || uri.scheme == "https"
126
+ step = transloadit.step(name, "/http/import",
127
+ url: uri.to_s,
128
+ )
129
+ elsif uri.scheme == "ftp"
130
+ step = transloadit.step(name, "/ftp/import",
131
+ host: uri.host,
132
+ user: uri.user,
133
+ password: uri.password,
134
+ path: uri.path,
135
+ )
136
+ else
137
+ raise Error, "Cannot construct a transloadit import step from #{io.inspect}"
138
+ end
139
+
140
+ step.options.update(step_options)
141
+
142
+ step
143
+ end
144
+
145
+ def transloadit_export_step(name, **step_options)
146
+ if defined?(Storage::S3) && storage.is_a?(Storage::S3)
147
+ step = transloadit.step(name, "/s3/store",
148
+ key: storage.s3.client.config.access_key_id,
149
+ secret: storage.s3.client.config.secret_access_key,
150
+ bucket: storage.bucket.name,
151
+ bucket_region: storage.s3.client.config.region
152
+ )
153
+ else
154
+ raise Error, "Cannot construct a transloadit export step from #{storage.inspect}"
155
+ end
156
+
157
+ step.options.update(step_options)
158
+
159
+ step
160
+ end
161
+
162
+ def transloadit_file(io = nil)
163
+ file = TransloaditFile.new(transloadit: transloadit)
164
+ file = file.add_step(transloadit_import_step("import", io)) if io
165
+ file
166
+ end
167
+
168
+ def transloadit_assembly(value, context: {}, **options)
169
+ options[:steps] ||= []
170
+ options[:fields] ||= {}
171
+
172
+ if (versions = value).is_a?(Hash)
173
+ options[:fields]["versions"] = {}
174
+ raise Error, "The versions Shrine plugin isn't loaded" if !defined?(Shrine::Plugins::Versions)
175
+ versions.each do |name, transloadit_file|
176
+ raise Error, "The given TransloaditFile is missing an import step" if !transloadit_file.imported?
177
+ unless transloadit_file.exported?
178
+ path = generate_location(transloadit_file, context.merge(version: name)) + ".${file.ext}"
179
+ export_step = transloadit_export_step("export_#{name}", path: path)
180
+ transloadit_file = transloadit_file.add_step(export_step)
181
+ end
182
+ options[:steps] |= transloadit_file.steps
183
+ options[:fields]["versions"][name] = transloadit_file.name
184
+ end
185
+ elsif (transloadit_file = value).is_a?(TransloaditFile)
186
+ raise Error, "The given TransloaditFile is missing an import step" if !transloadit_file.imported?
187
+ unless transloadit_file.exported?
188
+ path = generate_location(transloadit_file, context) + ".${file.ext}"
189
+ export_step = transloadit_export_step("export", path: path)
190
+ transloadit_file = transloadit_file.add_step(export_step)
191
+ end
192
+ options[:steps] += transloadit_file.steps
193
+ elsif (template = value).is_a?(String)
194
+ options[:template_id] = template
195
+ else
196
+ raise Error, "First argument has to be a TransloaditFile, a hash of TransloaditFiles, or a template"
197
+ end
198
+
199
+ if options[:steps].uniq(&:name) != options[:steps]
200
+ raise Error, "There are different transloadit steps using the same name"
201
+ end
202
+
203
+ transloadit.assembly(options)
204
+ end
205
+
206
+ def transloadit
207
+ @transloadit ||= self.class.transloadit
208
+ end
209
+ end
210
+
211
+ module FileMethods
212
+ def transloadit_response
213
+ @transloadit_response ||= (
214
+ body = metadata.fetch("transloadit_response")
215
+ body.instance_eval { def body; self; end }
216
+ response = ::Transloadit::Response.new(body)
217
+ response.extend ::Transloadit::Response::Assembly
218
+ response
219
+ )
220
+ end
221
+ end
222
+
223
+ class TransloaditFile
224
+ attr_reader :transloadit, :steps
225
+
226
+ def initialize(transloadit:, steps: [])
227
+ @transloadit = transloadit
228
+ @steps = steps
229
+ end
230
+
231
+ def add_step(*args)
232
+ if args[0].is_a?(::Transloadit::Step)
233
+ step = args[0]
234
+ else
235
+ step = transloadit.step(*args)
236
+ end
237
+
238
+ unless step.options[:use]
239
+ step.use @steps.last if @steps.any?
240
+ end
241
+
242
+ TransloaditFile.new(transloadit: transloadit, steps: @steps + [step])
243
+ end
244
+
245
+ # Transloadit in its result uses the name of the last step before the
246
+ # export step.
247
+ def name
248
+ if exported?
249
+ @steps[-2].name
250
+ else
251
+ @steps.last.name
252
+ end
253
+ end
254
+
255
+ def imported?
256
+ @steps.any? && @steps.first.robot.end_with?("/import")
257
+ end
258
+
259
+ def exported?
260
+ @steps.any? && @steps.last.robot.end_with?("/store")
261
+ end
262
+ end
263
+ end
264
+
265
+ register_plugin(:transloadit, Transloadit)
266
+ end
267
+ end
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = "shrine-transloadit"
3
+ gem.version = "0.1.0"
4
+
5
+ gem.required_ruby_version = ">= 2.1"
6
+
7
+ gem.summary = "Provides Transloadit integration for Shrine."
8
+ gem.homepage = "https://github.com/janko-m/shrine-transloadit"
9
+ gem.authors = ["Janko Marohnić"]
10
+ gem.email = ["janko.marohnic@gmail.com"]
11
+ gem.license = "MIT"
12
+
13
+ gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "*.gemspec"]
14
+ gem.require_path = "lib"
15
+
16
+ gem.add_dependency "shrine", "~> 2.1"
17
+ gem.add_dependency "transloadit", "~> 1.2"
18
+
19
+ gem.add_development_dependency "rake"
20
+ gem.add_development_dependency "minitest"
21
+ gem.add_development_dependency "minitest-hooks"
22
+ gem.add_development_dependency "dotenv"
23
+ gem.add_development_dependency "aws-sdk"
24
+ gem.add_development_dependency "sequel"
25
+ gem.add_development_dependency "sqlite3"
26
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shrine-transloadit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Janko Marohnić
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: shrine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: transloadit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-hooks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: dotenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: aws-sdk
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sequel
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sqlite3
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
140
+ email:
141
+ - janko.marohnic@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - LICENSE.txt
147
+ - README.md
148
+ - lib/shrine/plugins/transloadit.rb
149
+ - shrine-transloadit.gemspec
150
+ homepage: https://github.com/janko-m/shrine-transloadit
151
+ licenses:
152
+ - MIT
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '2.1'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.5.1
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Provides Transloadit integration for Shrine.
174
+ test_files: []
175
+ has_rdoc: