directwave 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENCE +9 -0
- data/README.md +318 -0
- data/Rakefile +20 -0
- data/directwave.gemspec +30 -0
- data/lib/directwave/mounter.rb +95 -0
- data/lib/directwave/orm/activerecord.rb +49 -0
- data/lib/directwave/railtie.rb +9 -0
- data/lib/directwave/uploader/accreditation.rb +63 -0
- data/lib/directwave/uploader/configuration.rb +68 -0
- data/lib/directwave/uploader/connection.rb +36 -0
- data/lib/directwave/uploader/paths.rb +51 -0
- data/lib/directwave/uploader/uploader.rb +54 -0
- data/lib/directwave/uploader/versions.rb +149 -0
- data/lib/directwave/version.rb +3 -0
- data/lib/directwave.rb +29 -0
- data/lib/generators/directwave_generator.rb +8 -0
- data/lib/generators/templates/directwave.rb +33 -0
- data/spec/.DS_Store +0 -0
- data/spec/directwave/.DS_Store +0 -0
- data/spec/directwave/fixtures/Uppercase.jpg +1 -0
- data/spec/directwave/fixtures/bork.ttxt +1 -0
- data/spec/directwave/fixtures/bork.txt +1 -0
- data/spec/directwave/fixtures/bork.txtt +1 -0
- data/spec/directwave/fixtures/case.JPG +1 -0
- data/spec/directwave/fixtures/landscape.jpg +0 -0
- data/spec/directwave/fixtures/new.jpeg +1 -0
- data/spec/directwave/fixtures/new.txt +1 -0
- data/spec/directwave/fixtures/old.jpeg +1 -0
- data/spec/directwave/fixtures/old.txt +1 -0
- data/spec/directwave/fixtures/portrait.jpg +0 -0
- data/spec/directwave/fixtures/sponsored.doc +1 -0
- data/spec/directwave/fixtures/test.jpeg +1 -0
- data/spec/directwave/fixtures/test.jpg +1 -0
- data/spec/directwave/fog.rb +0 -0
- data/spec/directwave/orm/active_record_spec.rb +8 -0
- data/spec/directwave/uploader/accreditation_spec.rb +42 -0
- data/spec/directwave/uploader/configuration_spec.rb +69 -0
- data/spec/directwave/uploader/connection_spec.rb +11 -0
- data/spec/directwave/uploader/paths_spec.rb +76 -0
- data/spec/directwave/uploader/uploader_spec.rb +33 -0
- data/spec/directwave/uploader/versions_spec.rb +88 -0
- data/spec/spec_helper.rb +19 -0
- metadata +200 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright © 2012 radiant.fm
|
4
|
+
|
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
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
# DirectWave
|
2
|
+
|
3
|
+
This gem provides a simple way to direct upload big files to Amazon S3
|
4
|
+
storage from Ruby applications and process it with cloud encoding service,
|
5
|
+
such as zencoder.com or pandastream.com.
|
6
|
+
|
7
|
+
It works well with Rack based web applications, such as Ruby on Rails.
|
8
|
+
|
9
|
+
Inspired by [CarrierWave](http://github.com/jnicklas/DirectWave) and used in [radiant.fm](http://radiant.fm)
|
10
|
+
|
11
|
+
## Information
|
12
|
+
|
13
|
+
* RDoc documentation [available on RubyDoc.info](http://rubydoc.info/gems/DirectWave/frames)
|
14
|
+
* Source code [available on GitHub](https://github.com/radiantfm/directwave)
|
15
|
+
|
16
|
+
## Getting Help
|
17
|
+
|
18
|
+
* Please report bugs on the [issue tracker]https://github.com/radiantfm/directwave/issues).
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Install the latest stable release:
|
23
|
+
|
24
|
+
[sudo] gem install directwave
|
25
|
+
|
26
|
+
In Rails, add it to your Gemfile:
|
27
|
+
|
28
|
+
``` ruby
|
29
|
+
gem 'directwave'
|
30
|
+
```
|
31
|
+
|
32
|
+
## Getting Started
|
33
|
+
|
34
|
+
Start off by generating an uploader:
|
35
|
+
|
36
|
+
rails generate directwave Audio
|
37
|
+
|
38
|
+
this should give you a file in:
|
39
|
+
|
40
|
+
app/uploaders/audio_uploader.rb
|
41
|
+
|
42
|
+
Now you can customize your uploader. It
|
43
|
+
should look something like this:
|
44
|
+
|
45
|
+
``` ruby
|
46
|
+
class AudioUploader < DirectWave::Uploader::Base
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Most of the time you are going to want to use DirectWave together with an ORM.
|
51
|
+
It is quite simple to mount uploaders on columns in your model, so you can
|
52
|
+
simply assign files and get going:
|
53
|
+
|
54
|
+
## ActiveRecord
|
55
|
+
|
56
|
+
Add a string column to the model you want to mount the uploader on:
|
57
|
+
|
58
|
+
``` ruby
|
59
|
+
add_column :tracks, :audio, :string
|
60
|
+
```
|
61
|
+
|
62
|
+
Open your model file and mount the uploader:
|
63
|
+
|
64
|
+
``` ruby
|
65
|
+
class Track < ActiveRecord::Base
|
66
|
+
mount_directwave :audio, AudioUploader
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Now you can cache files by assigning them to the attribute, they will
|
71
|
+
automatically be stored when the record is saved.
|
72
|
+
|
73
|
+
``` ruby
|
74
|
+
u = Track.new(:audio_from_key => params[:key])
|
75
|
+
u.save!
|
76
|
+
u.audio.url # => '/url/to/file.png'
|
77
|
+
```
|
78
|
+
|
79
|
+
## Rails
|
80
|
+
|
81
|
+
You can use different flash uploaders for multiple direct upload,
|
82
|
+
such as [Uploadify](http://sd.r). For example in Rails with CoffeeScript and Nokogiri
|
83
|
+
generate uploader controller at first:
|
84
|
+
|
85
|
+
rails g controller Uploads new create
|
86
|
+
|
87
|
+
and add following code:
|
88
|
+
|
89
|
+
``` ruby
|
90
|
+
class UploadsController < ApplicationController
|
91
|
+
def new
|
92
|
+
@uploader = Track.new.audio
|
93
|
+
end
|
94
|
+
|
95
|
+
def create
|
96
|
+
xml_doc = Nokogiri::XML(params[:xml])
|
97
|
+
|
98
|
+
@track = Track.new(audio_from_key: xml_doc.xpath('//Key').text)
|
99
|
+
@track.save
|
100
|
+
|
101
|
+
head :ok
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
when in `assets/javascript/uploads.js.coffe` insert:
|
107
|
+
|
108
|
+
``` html
|
109
|
+
$(document).ready ->
|
110
|
+
uploader = $("#uploadify")
|
111
|
+
uploader.uploadify {
|
112
|
+
uploader : "path/to/swf/uploader"
|
113
|
+
method : "post"
|
114
|
+
multi : true
|
115
|
+
auto : true
|
116
|
+
fileDataName : "file"
|
117
|
+
script : uploader.data("bucket) + ".s3.amazonaws.com"
|
118
|
+
scriptAccess : "always"
|
119
|
+
scriptData : {
|
120
|
+
"AWSAccessKeyId" : uploader.data("aws-access-key-id"),
|
121
|
+
"key" : uploader.data("key"),
|
122
|
+
"acl" : uploader.data("acl"),
|
123
|
+
"policy" : uploader.data("policy"),
|
124
|
+
"signature" : uploader.data("signature"),
|
125
|
+
"success_action_status" : "201"
|
126
|
+
},
|
127
|
+
onError : (event, id, file, error) -> console.log(error),
|
128
|
+
onComplete : (event, id, file, response, data) ->
|
129
|
+
$.ajax({
|
130
|
+
type : 'post',
|
131
|
+
url : '/uploads',
|
132
|
+
data : { xml: response },
|
133
|
+
cache : false
|
134
|
+
});
|
135
|
+
}
|
136
|
+
```
|
137
|
+
|
138
|
+
in `views/uploads/new.html.erb`:
|
139
|
+
|
140
|
+
``` html
|
141
|
+
<%= file_field_tag "uploadify" , "data-aws-access-key-id" => @uploader.s3_access_key_id,
|
142
|
+
"data-key" => @uploader.store_key,
|
143
|
+
"data-acl" => @uploader.s3_acl,
|
144
|
+
"data-policy" => @uploader.s3_policy,
|
145
|
+
"data-signature" => @uploader.s3_signature,
|
146
|
+
"data-bucker" => @uploader.s3_bucket %>
|
147
|
+
```
|
148
|
+
|
149
|
+
|
150
|
+
## Changing the directories
|
151
|
+
|
152
|
+
In order to change where uploaded files are stored, just override the `store_dir`
|
153
|
+
method:
|
154
|
+
|
155
|
+
``` ruby
|
156
|
+
class MyUploader < DirectWave::Uploader::Base
|
157
|
+
def store_dir
|
158
|
+
'/my/upload/directory'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
163
|
+
If you want change where files will be uploaded, override the `upload_dir`
|
164
|
+
method:
|
165
|
+
|
166
|
+
``` ruby
|
167
|
+
class MyUploader < DirectWave::Uploader::Base
|
168
|
+
def store_dir
|
169
|
+
'/my/upload/directory/tmp'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
## Adding versions
|
175
|
+
|
176
|
+
Often you'll want to add different versions of the same file.
|
177
|
+
There is built in support for this:
|
178
|
+
|
179
|
+
``` ruby
|
180
|
+
class Audio < DirectWave::Uploader::Base
|
181
|
+
version :aac do
|
182
|
+
def filename
|
183
|
+
# where @name name of version, for now "aac"
|
184
|
+
@filename ||= [extract(:guid), [@name, extract(:basename)].join("/") << ".aac"].join("/")
|
185
|
+
end
|
186
|
+
|
187
|
+
def process
|
188
|
+
# proccessing code goes here
|
189
|
+
# always call super at the begin
|
190
|
+
super
|
191
|
+
|
192
|
+
job = Zencoder::Job.create(
|
193
|
+
{
|
194
|
+
input: "s3://#{@uploader.s3_bucket}.s3.amazonaws.com/#{@uploader.versions[:original].key}",
|
195
|
+
outputs: [
|
196
|
+
{
|
197
|
+
label: "aac",
|
198
|
+
url: "s3://#{@uploader.s3_bucket}.s3.amazonaws.com/#{@uploader.versions[:aac].key}",
|
199
|
+
format: "aac",
|
200
|
+
notifications: [
|
201
|
+
{ url: "http://zencoderfetcher/", format: "json" }
|
202
|
+
]
|
203
|
+
} # aac
|
204
|
+
] # outputs
|
205
|
+
}
|
206
|
+
)
|
207
|
+
@uploader.model.job_id = job.body["id"]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
When this uploader is used, a version called aac is then created, which is processed with `process`.
|
214
|
+
The uploader could be used like this:
|
215
|
+
|
216
|
+
``` ruby
|
217
|
+
uploader.url # => '/url/to/original/file.png'
|
218
|
+
uploader.url(:original) # => '/url/to/original/file.png'
|
219
|
+
uploader.aac.url # => '/url/to/aac/file.png'
|
220
|
+
uploader.url(:aac) # => '/url/to/aac/file.png'
|
221
|
+
```
|
222
|
+
|
223
|
+
You can also override `global_process` method wich called after
|
224
|
+
all process within versions:
|
225
|
+
|
226
|
+
``` ruby
|
227
|
+
class Audio < DirectWave::Uploader::Base
|
228
|
+
version :aac
|
229
|
+
version :wav
|
230
|
+
|
231
|
+
def global_process
|
232
|
+
super
|
233
|
+
|
234
|
+
job = Zencoder::Job.create(
|
235
|
+
{
|
236
|
+
input: "s3://#{s3_bucket}.s3.amazonaws.com/#{versions[:original].key}",
|
237
|
+
outputs: [
|
238
|
+
{
|
239
|
+
label: "aac",
|
240
|
+
url: "s3://#{s3_bucket}.s3.amazonaws.com/#{versions[:aac].key}",
|
241
|
+
format: "aac",
|
242
|
+
notifications: [
|
243
|
+
{ url: "http://zencoderfetcher/", format: :json }
|
244
|
+
]
|
245
|
+
}, # aac
|
246
|
+
{
|
247
|
+
label: "wav",
|
248
|
+
url: "s3://#{s3_bucket}.s3.amazonaws.com/#{versions[:wav].key}",
|
249
|
+
format: "wav",
|
250
|
+
notifications: [
|
251
|
+
{ url: "http://zencoderfetcher/", format: :json }
|
252
|
+
]
|
253
|
+
} # wav
|
254
|
+
|
255
|
+
] # outputs
|
256
|
+
}
|
257
|
+
)
|
258
|
+
model.job_id = job.body["id"]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
## Providing a default URL
|
264
|
+
|
265
|
+
In many cases it might be a good idea to rovide a default url, a fallback in case
|
266
|
+
no file has been uploaded. You can do this easily by overriding the `default_url`
|
267
|
+
method in your uploader:
|
268
|
+
|
269
|
+
``` ruby
|
270
|
+
class Audio < DirectWave::Uploader::Base
|
271
|
+
def default_url
|
272
|
+
"/fallback/default.mp3"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
```
|
276
|
+
|
277
|
+
## Configuring DirectWave
|
278
|
+
|
279
|
+
DirectWave has a broad range of configuration options, which you can configure,
|
280
|
+
both globally and on a per-uploader basis:
|
281
|
+
|
282
|
+
``` ruby
|
283
|
+
DirectWave.configure do |config|
|
284
|
+
config.s3_access_key_id = "access_key_id"
|
285
|
+
config.s3_secret_access_key = "secret_access_key"
|
286
|
+
config.s3_bucket = "bucket"
|
287
|
+
config.s3_region = "region"
|
288
|
+
config.s3_access_policy = :private # or other valid value, see amazon s3 docs
|
289
|
+
end
|
290
|
+
```
|
291
|
+
If you're using Rails, create an initializer for this:
|
292
|
+
|
293
|
+
``` ruby
|
294
|
+
config/initializers/directwave.rb
|
295
|
+
```
|
296
|
+
|
297
|
+
## License
|
298
|
+
|
299
|
+
Copyright (c) 2012 radiant.fm
|
300
|
+
|
301
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
302
|
+
a copy of this software and associated documentation files (the
|
303
|
+
"Software"), to deal in the Software without restriction, including
|
304
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
305
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
306
|
+
permit persons to whom the Software is furnished to do so, subject to
|
307
|
+
the following conditions:
|
308
|
+
|
309
|
+
The above copyright notice and this permission notice shall be
|
310
|
+
included in all copies or substantial portions of the Software.
|
311
|
+
|
312
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
313
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
314
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
315
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
316
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
317
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
318
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'bundler'
|
10
|
+
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
require 'rake'
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
|
15
|
+
desc "Run all examples"
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
17
|
+
t.rspec_opts = %w[--color]
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => [:spec]
|
data/directwave.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "directwave/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "directwave"
|
7
|
+
s.version = Directwave::VERSION
|
8
|
+
s.authors = ["Dima Kochnev"]
|
9
|
+
s.email = ["kochnev.d@gmail.com"]
|
10
|
+
s.homepage = "http://radiant.fm"
|
11
|
+
s.summary = %q{Ruby direct uploader to Amazon S3}
|
12
|
+
s.description = %q{A simple way to direct upload big files to Amazon S3 storage from Ruby applications and process it with cloud encoding service.}
|
13
|
+
s.extra_rdoc_files = ["README.md"]
|
14
|
+
|
15
|
+
s.rubyforge_project = "directwave"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency "activesupport", ["~> 3.1"]
|
23
|
+
s.add_dependency "uuid"
|
24
|
+
s.add_dependency "aws-sdk"
|
25
|
+
|
26
|
+
s.add_development_dependency "rails", ["~> 3.1"]
|
27
|
+
s.add_development_dependency "rake"
|
28
|
+
s.add_development_dependency "rspec"
|
29
|
+
s.add_development_dependency "sqlite3"
|
30
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module DirectWave
|
2
|
+
|
3
|
+
##
|
4
|
+
# If a Class is extended with this module, it gains the mount_uploader
|
5
|
+
# method, which is used for mapping attributes to uploaders and allowing
|
6
|
+
# easy assignment.
|
7
|
+
#
|
8
|
+
# You can use mount_uploader with pretty much any class, however it is
|
9
|
+
# intended to be used with some kind of persistent storage, like an ORM.
|
10
|
+
#
|
11
|
+
module Mounter
|
12
|
+
|
13
|
+
##
|
14
|
+
# === Returns
|
15
|
+
#
|
16
|
+
# [Hash{Symbol => DirectWave}] what uploaders are mounted on which columns
|
17
|
+
#
|
18
|
+
|
19
|
+
def uploaders
|
20
|
+
@uploaders ||= {}
|
21
|
+
@uploaders = superclass.uploaders.merge(@uploaders) if superclass.respond_to?(:uploaders)
|
22
|
+
@uploaders
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Mounts the given uploader on the given column. This means that assigning
|
27
|
+
# and reading from the column will upload and retrieve files. Supposing
|
28
|
+
# that a Track class has an uploader mounted on audio, you can assign and
|
29
|
+
# retrieve files like this:
|
30
|
+
#
|
31
|
+
# @track.store_key = "s3/key/of/file"
|
32
|
+
# @track.audio # => <Uploader>
|
33
|
+
#
|
34
|
+
# @user.audio.url # => "url/to/original/version.aac"
|
35
|
+
#
|
36
|
+
# Passing a block makes it possible to customize the uploader. This can be
|
37
|
+
# convenient for brevity, but if there is any significatnt logic in the
|
38
|
+
# uploader, you should do the right thing and have it in its own file.
|
39
|
+
#
|
40
|
+
# === Added instance methods
|
41
|
+
#
|
42
|
+
# Supposing a class has used +mount_uploader+ to mount an uploader on a column
|
43
|
+
# named +image+, in that case the following methods will be added to the class:
|
44
|
+
#
|
45
|
+
# [audio] Returns an instance of the uploader only if anything has been uploaded
|
46
|
+
#
|
47
|
+
# === Parameters
|
48
|
+
#
|
49
|
+
# [column (Symbol)] the attribute to mount this uploader on
|
50
|
+
# [uploader (DirectWave::Uploader)] the uploader class to mount
|
51
|
+
# [&block (Proc)] customize anonymous uploaders
|
52
|
+
#
|
53
|
+
# === Examples
|
54
|
+
#
|
55
|
+
# Mounting uploaders on different columns.
|
56
|
+
#
|
57
|
+
# class Track
|
58
|
+
# mount_directwave :audio, AudioUploader
|
59
|
+
# mount_directwave :lyrics, LyricsUploader
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# This will add an anonymous uploader with only the default settings:
|
63
|
+
#
|
64
|
+
# class Data
|
65
|
+
# mount_uploader :csv
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# this will add an anonymous uploader overriding the upload_dir and store_dir:
|
69
|
+
#
|
70
|
+
# class Track
|
71
|
+
# mount_uploader :audio do
|
72
|
+
# def upload_dir
|
73
|
+
# "audio"
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# def store_dir
|
77
|
+
# "audio"
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
|
83
|
+
def mount_directwave(column, uploader=nil)
|
84
|
+
uploader = Class.new(uploader || DirectWave::Uploader::Base)
|
85
|
+
uploaders[column.to_sym] = uploader
|
86
|
+
|
87
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
88
|
+
def #{column}
|
89
|
+
@uploader ||= self.class.uploaders[:#{column}].new(self, :#{column})
|
90
|
+
end
|
91
|
+
RUBY
|
92
|
+
end
|
93
|
+
|
94
|
+
end # Mounter
|
95
|
+
end # DirectWave
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module DirectWave
|
4
|
+
module ActiveRecord
|
5
|
+
|
6
|
+
include DirectWave::Mounter
|
7
|
+
|
8
|
+
##
|
9
|
+
# See +DirectWave::Mounter#mount_uploader+ for documentation
|
10
|
+
#
|
11
|
+
# === Added instance methods
|
12
|
+
#
|
13
|
+
# Supposing a class has used +mount_uploader+ to mount an uploader on a column
|
14
|
+
# named +image+, in that case the following methods will be added to the class:
|
15
|
+
#
|
16
|
+
# [#{column}_from_key] Returns the key of assigned file
|
17
|
+
# [#{column}_from_key=] Assign file from S3 key
|
18
|
+
#
|
19
|
+
|
20
|
+
def mount_directwave(column, uploader=nil)
|
21
|
+
super
|
22
|
+
|
23
|
+
instance_eval <<-RUBY, __FILE__, __LINE__+1
|
24
|
+
RUBY
|
25
|
+
|
26
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
27
|
+
attr_accessible :#{column}_from_key
|
28
|
+
|
29
|
+
def #{column}_from_key
|
30
|
+
send(:#{column}).store_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def #{column}_from_key=(string)
|
34
|
+
send(:#{column}).store_key = string
|
35
|
+
end
|
36
|
+
|
37
|
+
before_save do
|
38
|
+
send(:#{column}).save
|
39
|
+
end
|
40
|
+
|
41
|
+
after_destroy do
|
42
|
+
send(:#{column}).destroy
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
end
|
46
|
+
end # ActiveRecord
|
47
|
+
end # DirectWave
|
48
|
+
|
49
|
+
ActiveRecord::Base.extend DirectWave::ActiveRecord
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module DirectWave
|
2
|
+
|
3
|
+
module Uploader
|
4
|
+
module Accreditation
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
##
|
9
|
+
# === Returns
|
10
|
+
#
|
11
|
+
# [String] Amazon S3 acl
|
12
|
+
#
|
13
|
+
def s3_acl
|
14
|
+
@s3_acl ||= s3_access_policy.to_s.gsub("_", "-")
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# === Returns
|
19
|
+
#
|
20
|
+
# [Boolean] Amazon S3 policy
|
21
|
+
#
|
22
|
+
def s3_policy
|
23
|
+
@s3_policy ||= Base64.encode64(
|
24
|
+
{
|
25
|
+
"expiration" => expiration_date,
|
26
|
+
"conditions" => [
|
27
|
+
{"bucket" => s3_bucket},
|
28
|
+
["starts-with", "$key", upload_dir],
|
29
|
+
{"success_action_status" => "201"},
|
30
|
+
["starts-with", "$filename", ""],
|
31
|
+
["starts-with", "$folder", ""],
|
32
|
+
{"acl" => s3_acl},
|
33
|
+
["content-length-range", 1, max_file_size]
|
34
|
+
]
|
35
|
+
}.to_json
|
36
|
+
).gsub("\n","")
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# === Returns
|
41
|
+
#
|
42
|
+
# [Boolean] Amazon S3 signature
|
43
|
+
#
|
44
|
+
def s3_signature
|
45
|
+
@s3_signature ||= Base64.encode64(
|
46
|
+
OpenSSL::HMAC.digest(
|
47
|
+
OpenSSL::Digest::Digest.new("sha1"),
|
48
|
+
s3_secret_access_key, s3_policy
|
49
|
+
)
|
50
|
+
).gsub("\n","")
|
51
|
+
end
|
52
|
+
end # InstanceMethods
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def guid
|
57
|
+
UUID.generate
|
58
|
+
end
|
59
|
+
|
60
|
+
end # Accreditation
|
61
|
+
end # Uploader
|
62
|
+
|
63
|
+
end # DirectWave
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module DirectWave
|
2
|
+
|
3
|
+
module Uploader
|
4
|
+
module Configuration
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
add_config :s3_access_policy
|
9
|
+
add_config :s3_bucket
|
10
|
+
add_config :s3_access_key_id
|
11
|
+
add_config :s3_secret_access_key
|
12
|
+
add_config :s3_region
|
13
|
+
add_config :s3_authentication_timeout
|
14
|
+
|
15
|
+
add_config :max_file_size
|
16
|
+
add_config :expiration_date
|
17
|
+
|
18
|
+
add_config :store_dir
|
19
|
+
add_config :upload_dir
|
20
|
+
|
21
|
+
reset_config
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def add_config(name)
|
26
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
27
|
+
class << self
|
28
|
+
def #{name}(value=nil)
|
29
|
+
@#{name} = value if value
|
30
|
+
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
31
|
+
name = superclass.#{name}
|
32
|
+
return nil if name.nil? && !instance_variable_defined?("@#{name}")
|
33
|
+
@#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
|
34
|
+
end
|
35
|
+
|
36
|
+
def #{name}=(value)
|
37
|
+
@#{name} = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def #{name}
|
42
|
+
self.class.#{name}
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
end
|
46
|
+
|
47
|
+
def configure
|
48
|
+
yield self
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset_config
|
52
|
+
configure do |config|
|
53
|
+
config.s3_access_policy = :public_read
|
54
|
+
config.s3_region = "us-east-1"
|
55
|
+
config.s3_authentication_timeout = 60.minutes
|
56
|
+
|
57
|
+
config.max_file_size = 300.megabytes
|
58
|
+
config.expiration_date = 6.hours.from_now.utc.iso8601
|
59
|
+
|
60
|
+
config.store_dir = "uploads"
|
61
|
+
config.upload_dir = "uploads/tmp"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end # ClassMethods
|
65
|
+
end #Configuration
|
66
|
+
end # Uploader
|
67
|
+
|
68
|
+
end # DirectWave
|